1.在应用中,可通过消息服务中间件来提升系统异步通信,扩展解耦能力
2.消息服务中两个中主要概念:
消息代理(message broker) 和目的地(distination)
当消息发送者发送消息以后,将由消息代理接管,消息代理保证消息传递到指定目的地
3.消息队列主要有两种形式的目的地
队列(queue):点对点消息通信
主题(topic):发布(publish)/订阅(subscribe)消息通信
4.点对点式(只有一个消费者):
消息发送者发送消息,消息代理将其放入一个队列中,消息接收者从队列中获取消息内容,消息读取后被移出队列
消息只有唯一的发送者和接受者,但并不是说只能有一个接收者
5.发布式订阅(多个消费者)
发送者(发布者)发送消息到主题,多个接收者(订阅者)监听(订阅)这个主题,那么就会在消息到达同时收到消息
6.JMS(Java Message Service)JAVA API消息服务:
基于JVM消息代理的规范,ActiveMQ,HornetMQ是JMS实现
7.AMQP(Advanced Message Queuing Protocol)网络线级协议
高级消息队列协议,也是一个消息代理的规范,兼容JMS
RabbitMQ是AMQP的实现。
8.JMS和AMQP对比
JMS | AMQP | |
定义 | Java API | 网络栈协议 |
跨语言 | 否 | 是 |
跨平台 | 否 | 是 |
Model | 提供两种消息模型: 1.Peer-2-Peer 2.Pub/Sub |
提供了5种消息模型: 1.direct exchange(点对点) 2.fanout exchange 3.topic exchange 4.headers exchange 5.system exchange 本质来讲,后四种和JMS的pub/sub模型没有太大的区别,仅实在路由机制上做客更详细的划分 |
支持消息类型 | 多种消息类型: TextMessage MapMessage ByteMessage StreamMessage ObjectMessage Message(只有消息头和属性) |
byte[]当实际应用时,有复杂的消息,可以将消息序列化后发送。 |
总结 | JMS定义了JAVA API层面的标准,在java体系中,多个client均可以通过JMS进行交互,不需要应用修改代码,但是其对跨平台的支持较差。 | AMQP定义了wire-level层的协议标准,天然具有跨平台,跨语言特性。 |
9.Spring支持
spring-jms提供了队JMS的支持
spring-rabbit提供了队AMQP的支持
需要ConnectionFactory的实现来连接消息代理
提供JmsTemplate,RabbitTemplate来发送消息
@JmsListener(JMS) ,@RabbitListener(AMQP)注解在方法上监听消息代理发布消息
@EnableJms。@EnableRabbit开启支持
10.Spring Boot自动配置
JmsAutoConfiguration
RabbitAutoConfiguration
1.使用消息队列加快速度
三种消息传送的对比可看出使用消息队列明显加快了速度。
2.应用解耦
3.流量削峰
* RabbitMQ 是由erlang开发的AMQP的开源实现 * 核心概念: * Message:消息,由消息头和消息体组成,消息头由一系列的可选属性组成,包括routing-key(路由键) * ,priority(相对其他消息的优先权),delivery-mode(指出该消息可能需要持久性存储)等。 * Publisher:消息生产者,也是一个向交换器发布消息的客户端应用程序。 * Exchange:交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。有四种类型:direct,fanout,topic,headers * Queue:消息队列,用来保存消息知道发送给消费者,一个消息可投入一个或多个队列 * Binding:绑定,用于消息队列和交换器之间的关联,Exchange和Queue的绑定可以是多对多的关系 * Connection:网络连接 * Channel:信道,多路复用连接中的一条独立的双向数据流通道,信道的建立在真实的TCP连接内的虚拟连接,AMQP命令 * 都是通过信道发出去的,不管是发布消息,订阅队列还是接收消息,这些动作都是通过信道完成,因为对于操作系统来说 * 建立和销毁TCP都是非常昂贵的开销,所以引入了信道的概念,以复用一条TCP连接。 * Consumer:消费者。 * Virual Host:虚拟主机,表示一批交换器,消息队列和相关对象,是共享相同身份认证和加密环境的独立服务器域,每个vhost * 本质上就是一个mini版的RabbitMQ服务器,拥有自己的队列,交换器,绑定和权限机制。vhost是AMQP概念的基础,必须在 * 连接时指定RabbitMQ默认的vhost是/。 * Broker:表示消息队列服务器实体。 * RabbitMQ运行机制 * AMQP中的消息路由:AMQP中的消息的路由过程和Java开发者熟悉的JMS存在一些差别,AMQP中增加了Exchange和Binding的角色。 * 生产者把消息发布到Exchange上,消息最终到达队列并被消费,而binding决定交换器的消息应该发往那个队列。 * RabbitMQ整合: * 1.引入spring-boot-starter-amqp * 2.application.yml配置 * 3.测试RabbitMQ:AmqpAdmin(管理组件)RabbitTemplate(消息发送处理组件)
* RabbitMQ自动配置类 * 1.RabbitAutoConfiguration * 2.有自动配置的连接工厂ConnectionFactory * 3.RabbitProperties 封装了 RabbitMQ的配置 * 4.RabbitTemplate: 给RabbitMQ发送和接收消息 * 5.AmqpAdmin:RabbitMQ系统管理功能组件 * AmqpAdmin:创建和删除Queue,Exchange,Binding * 6.@Enable+@RabbitListener 监听消息队列的内容
需前置Erlang开发环境,推荐使用docker部署。
window下载傻瓜式教程:windows10环境下的RabbitMQ安装步骤(图文) - 清明-心若淡定 - 博客园
1.创建新的交换机
Name:名称
Type:连接方式
Durability:持久化方式
2.创建队列
3.交换机绑定队列
4.发送消息
5.队列收到消息
1.导入坐标
org.springframework.boot
spring-boot-starter-amqp
2.开启注解
@SpringBootApplication
@EnableRabbit //开启基于注解的RabbitMQ模式
public class Springboot01CacheApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot01CacheApplication.class, args);
}
}
3.测试使用RabbitMQ
public class RabbitMQService {
@Autowired
RabbitTemplate rabbitTemplate;
//发送消息
public void contextLoads(){
//Message需要自己构造一个,定义消息头和内容
//rabbitTemplate.send(exchange,roouteKey,message);
//object默认当成消息体,只需要传入要发送的对象,自动序列化发送给rabbitmq
//rabbitTemplate.convertAndSend(exchange,routeKey,object);
Map map = new HashMap<>();
map.put("msg","这是一个消息!");
map.put("data", Arrays.asList("hello world!",123,true));
//对象被默认序列化以后发送出去,需要转json
rabbitTemplate.convertAndSend("exchange.direct","xuyu",map);
rabbitTemplate.convertAndSend("exchange.direct","xuyu",new Employee(1,"employee","xuyu","[email protected]","Male",1));
}
//接收消息
public void receiver(){
rabbitTemplate.receiveAndConvert("xuyu");
}
//监听消息
@RabbitListener(queues = "xuyu") //需要在启动类上加@EnableRabbit注解
public void receive(Book book){
System.out.println("接收消息:"+book);
}
}
4.序列化json格式
@Configuration
public class RabbitMQConfig {
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
5.手动配置交换机
public class RabbitMQAdmin {
@Autowired
AmqpAdmin amqpAdmin;
public void createExchange(){
//创建交换机
amqpAdmin.declareExchange(new DirectExchange("amqpadmin.exchange"));
//创建队列
amqpAdmin.declareQueue(new Queue("amqpadmin.queue",true));
//创建绑定规则
amqpAdmin.declareBinding(new Binding("amqpadmin.queue", Binding.DestinationType.QUEUE,"amqpadmin.exchange","xuyu",null));
}
}