SpringBoot——消息
一、消息服务的基本概念
1、消息服务中两个重要概念:
消息代理(message broker,消息服务器)和目的地(destination)当消息发送者发送消息以后,将由消息代理接管,消息代理保证消息传递到指定目的地。
2、消息队列主要有两种形式的目的地:
(1) 队列(queue):点对点消息通信(point-to-point)。
- 发送者发送消息,消息代理将其放入一个队列中,在合适的时候,消息接收者从队列中获取消息内容。
(2) 主题(topic):发布(publish)/订阅(subscribe)消息通信。
- 发送者发送消息到主题,多个接收者订阅这个主题,那么就会在消息到达时,同时收到消息。
3、消息队列主要可以完成:
(1)异步处理
应用请求不用依次进行处理,提升整体系统的吞吐能力。
(2)应用间解耦
应用间进行关联时,无需植入过多的接口,能够极大的减少耦合程度。
(3)流量削峰
当处理秒杀类业务时,能够让后端服务器依据自己的能力来处理业务,可以在一定程度上减少服务器的压力,防止冲垮服务器。
4、消息服务协议规范
(1)JMS(Java Message Service)JAVA消息服务
- Java API
- JMS 定义了JAVA API层面的标准;在java体系中,多个clien均可以通过JMS进行交互,不需要应用修改代码,但是其对跨平台的支持较差。
- 基于JVM消息代理的规范,ActiveMQ、HornetMQ是JMS实现。
(2)AMQP(Advanced Message Queuing Protocol)
- 网络级协议
- 高级消息队列协议,也是一个消息代理的规范,兼容JMS
- AMQP定义了wire-level层的协议标准;天然具有跨平台、跨语言特性。
- RabbitMQ是AMQP的实现。
(3)JMS和AMQP对比
JMS | AMQP | |
---|---|---|
定义 | Java API | 网络级协议 |
是否跨平台/语言 | 否 | 是 |
消息模型 | (1)点对点 (2)发布/订阅 |
(1)direct exchange (2)fanout exchange (3)topic change (4)headers exchange (5)system exchange 后四种和JMS的pub/sub模型没有太大差别,仅是在路由机制上做了更详细的划分; |
支持消息类型 | TextMessage、 MapMessage、 BytesMessage、 StreamMessage、 ObjectMessage、 Message (只有消息头和属性) |
byte[] 当实际应用时,有复杂的消息,可以将消息序列化后发送。 |
5、Spring对消息服务的支持
- spring-jms提供了对JMS的支持
- spring-rabbit提供了对AMQP的支持 需要ConnectionFactory的实现来连接消息代理
- 提供JmsTemplate、RabbitTemplate来发送消息
- @JmsListener(JMS)、@RabbitListener(AMQP)注解在方法上监听消息代理发布的消息
- @EnableJms、@EnableRabbit开启支持
6、SpringBoot对消息服务的配置
- JmsAutoConfiguration
- RabbitAutoConfiguration
二、AMQP实现——RabbitMQ
RabbitMQ是一个基于erlang语言开发的AMQP(Advanved Message Queue Protocol)开源实现。
1、基本概念
(1)Message
消息由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。
(2)Publisher
消息的生产者,是一个向交换器发布消息的客户端应用程序。
(3)Exchange
服务器中的交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列,交换器决定了消息的去向。Exchange有4种类型:direct(默认),fanout, topic, 和headers。
(4)Queue
消息队列,用来保存消息。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息在队列里面,等待消费者连接到这个队列将其取走。
(5)Binding
绑定,用于消息队列和交换器之间的关联。绑定就是用路由键将交换器和消息队列连接起来的路由规则。Exchange 和Queue的绑定可以是多对多的关系。
(6)Connection
网络连接,比如一个TCP连接。
(7)Channel
信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内的虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条TCP 连接。
(8)Consumer
消息的消费者,可以从消息队列中取得消息的客户端应用程序。
(9)Virtual Host
虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个vhost 本质上就是一个mini 版的RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是AMQP 概念的基础,必须在连接时指定,
RabbitMQ 默认的vhost 是/
。
(10)Broker
表示消息队列服务器实体
2、RabbitMQ的运行机制
(1)AMQP 中的消息路由
AMQP 中消息的路由过程和Java 开发者熟悉的JMS 存在一些差别,AMQP 中增加了Exchange 和Binding 的角色。生产者把消息发布到Exchange 上,而Binding 决定交换器的消息应该发送到那个队列。
(2)Exchange
Exchange分发消息时不同分发策略有所区别,目前共四种类型:direct、fanout、topic、headers 。headers 匹配消息队列通过AMQP 消息的header而不是路由键,目前几乎用不到了。
direct: 消息中的路由键(routing key)需要与队列名完全匹配。
fanout:(发布/订阅) 每个发到fanout 类型交换器的消息都会分到所有绑定的队列上去。fanout 交换器不处理路由键,很像子网广播,每台子网内的主机都获得了一份复制的消息。fanout 类型转发消息是最快的。
topic: 将路由键和某个模式进行匹配。两个通配符:#
匹配0个或多个单词,*
匹配一个单词。
3、RabbitMQ安装与测试
(1)拉取RabbitMQ
docker pull 阿里云镜像加速地址/library/rabbitmq:3-management
(2)查看是否安装成功
docker images
(3)启动RabbitMQ
5672:服务器端口
15672:后台管理界面端口
docker run -d -p 5672:5672 -p 15672:15672 --name myRabbitMQ 92c743b6c055
(4)查看运行的容器
docker ps
(5)访问后台管理界面
默认用户名/密码为:guest/guest
(6)测试
1)添加交换器和队列
添加一个新的exchange
一共添加了三个交换器:
添加四个队列:
2)绑定
direct绑定:
fanout绑定:
无需绑定路由规则。
topic绑定:
3)发送消息测试:
对于队列,只有路由键和队列名完全匹配才可以。
收到消息:
对于fanout,无论路由键是什么,都是以广播的形式发给所有队列:
对于主题:
只有匹配指定路由规则的队列才可以收到消息,这里只有cbj.news和glp.news可以收到消息。
4、SpringBoot和RabbitMQ整合
RabbitAutoConfiguration
RabbitProperties:封装了RabbitMQ的配置
RabbitTemplate:给RabbitMQ发送和接收消息
AmqpAdmin :系统管理功能组件
(1)引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
(2)application.properties配置
spring.rabbitmq.host=47.94.230.49
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
(3)测试RabbitMQ
发送消息/接收消息
- send(exchange,routekey,message);使用send发送消息,message需要自己构建(包括消息头和消息体)
- convertAndSend(exchange,routeKey,object):object默认作为消息体,并且会自动序列化发送给Rabbitmq.
RabbitMQ管理界面得到的数据:
RabbitTemplate在处理消息时,默认使用SimpleMessageConverter():
在RabbitAutoConfiguration中配置RabbitTemplate时,可以从容器中导入自己的MessageConverter:
(4)自定义一个MessageConverter
@Configuration
public class myAMQPConfig {
@Bean
public MessageConverter myMessageconverter(){
return new Jackson2JsonMessageConverter();
}
}
配置完消息转换器之后:
(5)监听消息列表
监听消息列表,实时接收消息
使用@RabbitListener
来监听消息,需要开启Rabbit相关的注解@EnableRabbit
。
在主启动类上加上注解:@EnableRabbit
可以利用Message获取消息体以及消息头
(6)在Java程序中创建Exchange、队列以及绑定规则
AmqpAdmin:管理组件,用来创建Exchange,Queue,Binding
创建Exchange:
创建队列:
创建绑定关系:
Binding(
String destination, 要绑定的目的地
Binding.DestinationType destinationType, 目的地类型
String exchange, 交换器
String routingKey, 路由规则
@Nullable Map<String, Object> arguments 参数
)
三、JMS实现——ActiveMQ
待更新