前言:学习rabbitMQ应知道
1.什么是JMS
JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。
JMS是一种与厂商无关的 API,用来访问消息收发系统消息,它类似于JDBC。这里,JDBC 是可以用来访问许多不同关系数据库的API,而JMS则提供同样与厂商无关的访问方法,以访问消息收发服务。
2.什么是AMQP
AMQP,即Advanced Message Queuing Protocol(高级消息队列协议),一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现有 RabbitMQ等。
在异步通讯中,消息不会立刻到达接收方,而是被存放到一个容器中,当满足一定的条件之后,消息会被容器发送给接收方,这个容器即消息队列,而完成这个功能需要双方和容器以及其中的各个组件遵守统一的约定和规则,AMQP就是这样的一种协议,消息发送与接受的双方遵守这个协议可以实现异步通讯。这个协议约定了消息的格式和工作方式。
3.JMS和AMQP的区别
总结来说:
1)JMS是定义了统一的接口,来对消息操作进行统一;AMQP是通过规定协议来统一数据交互的格式
2)JMS限定了必须使用Java语言;AMQP只是协议,不规定实现方式,因此是跨语言的。
3)JMS规定了两种消息模型;而AMQP的消息模型更加丰富
JMS两种模型:
点对点:Point-to-Point(P2P)
(1) 每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中)
(2) 发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列。
(3) 接收者在成功接受消息之后需要向队列应答成功
发布订阅:Publish/Subscribe(Pub/Sub)
(1) 每个消息可以有多个消费者
(2) 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅之后,才能消费发布者的消息,而且,为了消费消息,订阅者必须保持运行的状态。
简介
rabbitMQ 支持6中消息队列 但是rpc不属于mq 所有 只剩5 种 分别是 简单队列,工作队列,订阅模式,路由模式,通配符模式
我们的消息发出后是否被成功消费 rabbitMq给我们提供了 ack确认机制 可以手动确认,也可以自动确认,
简单队列:一对一 即 生产者:消费者(绑定同一个队列queue)
工作队列:一对多(一个队列queue多个消费者) 即 生产者:{消费者,消费者,…} 但是可根据其消费的能力,使用能者多劳政策(即一次只给一个信息消费,消费完再给)
订阅模式:我们将消息(生产者)交给交换机,由交换机在转交给多个队列 即 一个生产者发送的消息会被多个消费者获取
路由模式:生产者发送消息到交换机并且要指定路由key,消费者将队列绑定到交换机时需要指定路由key,两者key相匹配,则消息会发送到对应队列中
通配符模式:生产者发送消息到交换机并且要指定路由key,消费者将队列绑定到交换机时需要指定路由key
通配符模式 生产者P发送消息到交换机X,type=topic,交换机根据绑定队列的routing key的值进行通配符匹配;符号#:匹配一个或者多个词lazy.# 可以匹配lazy.irs或者lazy.irs.cor 符号*:只能匹配一个词lazy.* 可以匹配lazy.irs或者lazy.cor
Spring整合rabbitMQ
引入依赖
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
我们需要两个项目,一个生产者每一个消费者,或多个消费者
编写生产者发送消息
在resources下编写
rabbit.properties
rabbitmq.host=localhost
rabbitmq.port=5672
rabbitmq.username=guest
rabbitmq.password=guest
rabbitmq.vhost=/
表写applicationContext-rabbit.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
<!-- 创建连接工厂 -->
<rabbit:connection-factory id="connectionFactory"
host="${rabbitmq.host}" port="${rabbitmq.port}" username="${rabbitmq.username}"
password="${rabbitmq.password}" virtual-host="${rabbitmq.vhost}" />
<!-- admin管理工具 -->
<rabbit:admin connection-factory="connectionFactory" />
<!-- 交换机 durable是否持久化 -->
<rabbit:topic-exchange name="TAOTAO_ITEM_EXCHANGE"
auto-declare="true" durable="true" />
<!-- 模板对象 -->
<rabbit:template id="taotao_template" exchange="TAOTAO_ITEM_EXCHANGE"
connection-factory="connectionFactory" />
</beans>
连接我们的rabbitMQ :
指定我们的交换机:
交换机绑定到模板对象:
记得在spring主配置文件中读取 :
编写RabbitService 发送消息工具
package com.dxsysg.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
* @author zhaozeren
* @version 1.0
* @date 2019/3/29
*/
@Service
public class RabbitService {
private final ObjectMapper objectMapper = new ObjectMapper();
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendMsg(Long id, String type){
try {
//根据实际业务传送消息
Map<String, Object> map = new HashMap<>();
map.put("id", id);//商品的ID
map.put("type", type);//所做操作,update,delete...
map.put("date", System.currentTimeMillis());//发送时间
this.rabbitTemplate.convertAndSend("item." + type, objectMapper.writeValueAsString(map));
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试当商品有改动后发送消息:
启动项目:
我们会发现在rabbit的管理界面http://localhost:15672
发现多出了交换机
编写消费者
引入依赖
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
在resources下编写
rabbit.properties
rabbitmq.host=localhost
rabbitmq.port=5672
rabbitmq.username=guest
rabbitmq.password=guest
rabbitmq.vhost=/
表写applicationContext-rabbit.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
<!-- 创建连接工厂 -->
<rabbit:connection-factory id="connectionFactory"
host="${rabbitmq.host}" port="${rabbitmq.port}" username="${rabbitmq.username}"
password="${rabbitmq.password}" virtual-host="${rabbitmq.vhost}" />
<!-- admin管理工具 -->
<rabbit:admin connection-factory="connectionFactory" />
<!-- 队列 durable是否持久化 -->
<rabbit:queue name="TAOTAO_WEB_ITEM_QUEUE" auto-declare="true" durable="false" />
<!-- 监听 -->
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="itemMQListener" method="consume" queue-names="TAOTAO_WEB_ITEM_QUEUE"/>
</rabbit:listener-container>
<!-- 消费者 -->
<bean id="itemMQListener" class="com.example.rabbit.ItemMQListener"/>
</beans>
声明队列:
定义消费者:
监听:
表写消费者类ItemMQListener:
package com.example.rabbit;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
/**
* @author zhaozeren
* @version 1.0
*/
public class ItemMQListener {
private static final ObjectMapper MAPPER = new ObjectMapper();
public void consume(String msg){
Long itemId = null;
String type = null;
try {
JsonNode jsonNode = MAPPER.readTree(msg);
//获取消费信息中的id
itemId = jsonNode.get("id").asLong();
//获取消费信息中的type
type = jsonNode.get("type").toString();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(itemId);
System.out.println(type);
}
}
启动项目:
我们会发现在rabbit的管理界面http://localhost:15672
我们发现多处了个队列:
队列绑定交换机
在界面管理工具中完成绑定关系
找到Exchange管理页面:
点击TAOTAO-ITEM-EXCHANGE,即可进入管理页,在这里绑定队列:
指定我们的队列,我们所需要的key, 绑定队列.(我们采用了通配符模式)
测试,分别起动消费者,生产者项目;
发送消息:
消费者: