应用场景:
实现系统异步通讯
扩展解耦能力
访问高峰期服务器人数控制
用户 -->注册系统(50MS)-->邮件发送(50MS)-->发送短信(50MS)-->响应用户注册成功
可以使用消息中间件(使用异步消息处理) 邮件发送
用户 -->注册系统(50MS)-->mq(50MS) 短信发送 -->响应用户(55MS)
例如在后台添加一个商品后,将商品信息同步到全文检索中
写在一个项目中体现不出只能单一原则,而且导致两个服务之间的引用,从而引起了服务治理混乱
使用消息队列解耦
后台管理系统-->发布消息队列mq<-- 搜索系统订阅消息
消息发送者发送消息,消息代理将其放入到一个队列中,消息接收者从队列中获取消息内容,消息读取后被移出队列
(消息有唯一的接收者和发送者)
发布者发布消息到主题,多个接收者(订阅者)订阅(监听)这个主题,那么就会在消息到达同时收到消息
JAVA MESSAGE SERVICE(java消息服务)
--是基于JVM消息代理的规范。
--ActiveMQ是JMS实现
Advanced Message Queuing Protocal
--高级消息队列协议,也是一个消息代理的规范,兼容JMS
--RabbitMQ是AMQP的实现
jms:是javaAPI规范的
AMQP:是基于网络线级协议
--spring提供了JmsTemlate、RabbitTemplate来发送消息
--@JmsListener(JMS) 用该注解在方法上监听消息代理发布的消息
--@RabbitListener(AMQP) 用该注解在方法上监听消息代理发布的消息
开启监听支持
--@EnableJms
--@EnableRabbit
springBoot自动配置
--JmsAutoConfigation
--RabbitAutoConfiguration
--Message
消息。由消息头和消息体组成
消息头:由一系列所选属性组成。routing-key(路由键--决定发送给谁)
priority(消息的优先权)
delivery-mode(指出该消息可能需要持久性存储)等
消息体:消息的内容(是不透明的)
--publisher
消息的生产者
--Exchange
交换器(用来接收声称这发送的消息并且将这些消息路由给服务器中的队列)
direct:是默认的,能实现jms中的点对点
fanout,topic和headers:能发布订阅模型
--Queue
消息队列,用来保存消息直到发送给消费者(消息容器)
--Binding
绑定,用于消息队列和交换器之间关联
--COnnection
网路连接
--Channel
信道。多路复用连接中的一条独立的双向数据流通道
--Consumer
消费者
--Virtual Host
虚拟主机。表示一批交换器、消息队列和相关对象
--Broker
表示消息队列服务器实体
3.1消息路由
AMQP中消息的路由过程和java开发者熟悉的JMS存在一些差别,AMQP中增加消费者接受,而Binding决定交换器的消息应该发送到那个队列。
3.2Exchange类型
分发消息时根据类型的不同分发策略有区别,目前有四种类型:
direct、fanout、topic和headers
direct(就是点对点)
4.1下载镜像
docker pull registry.docker-cn.com/library/rabbitmq:3-management
4.2启动
docker run -d -p 5672:5672 -p 15672:15672 --name myrabbitmq imagesid
4.3到管理首页
服务器ip地址:15672
4.4测试
message:
exchange.direct
exchange.fanout
exchange.topic
queue
kgc
kgc.news
kgc.student
bdqn.news
topic在绑定的时候注意:
kgc.#(其中#表示一个或多个单词)
*.news(其中 *表示匹配一个)
direct:是完全匹配路由键
fanout:是广播
topic:是匹配的方式
5.1需要的jar包依赖
Integration:RabbitMQ
Web:web
5.2application.properties
spring.rabbitmq.host=192.168.25.130
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#spring.rabbitmq.virtual-host=/
#spring.rabbitmq.port=5672
5.3测试direct
@Test
public void testPublishDirect(){
Map map = new HashMap<>();
map.put("msg","来自于direct,发送到kgc.news");
map.put("list", Arrays.asList("集合1","集合2","集合3"));
rabbitTemplate.convertAndSend("exchange.direct","kgc.news",map);
}
@Test
public void testReceiveDirect(){
Object object = rabbitTemplate.receiveAndConvert("kgc.news");
System.out.println(object.getClass());
System.out.println(object);
}
5.4可以自定义转换方式
@Configuration
public class MyAMQPConfig{
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
5.5fanout(广播)
//广播
@Test
public void testPublishFanout(){
Map map = new HashMap<>();
map.put("msg","来自于direct,发送到kgc.news");
map.put("list", Arrays.asList("fanout1","fanout2","fanout3"));
rabbitTemplate.convertAndSend("exchange.fanout","",map);
}
5.6注解监听
5.6.1开始注解
在springboot注解下添加开启rabbitmq注解
@SpringBootApplication
@EnableRabbit //开启rabbitmq注解
5.6.2消息监听
@Service
public class MyListener {
@RabbitListener(queues = "bdqn.news")
public void receive(Map map){
System.out.println(map);
}
}
6.1创建Exchange
@Autowired private AmqpAdmin amqpAdmin; //创建exchange @Test public void createExchange(){ amqpAdmin.declareExchange(new DirectExchange("amqp.exchange")); } }
6.2创建Queue
//创建queue @Test public void createQueue(){ amqpAdmin.declareQueue(new Queue("amqp.queue",true)); }
6.3绑定
//将queue绑定到exchange中 @Test public void bindingQueue(){ amqpAdmin.declareBinding(new Binding("amqp.queue", Binding.DestinationType.QUEUE,"qmqp.exchange","amqp.test",null)); }