springboot消息服务
JMS(java message service)消息服务:java原生的,不能跨平台;ActiveMQ
AMQP(advanved message queue protocol)高级消息队列()跨平台,只能发送字节序列;RabbitMQ
--------
RabbitMQ
核心概念:
Message:消息,消息是不具名的,它由消息头和消息体组成的。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)
、priority(相对于其他的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。
publisher:消息生产者,也是一个向交换器发布消息的客户端应用程序
Exchange:交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。Exchange有4中类型:direct(默认,点对点)、fanout,topic和headers,
不同类型的Exchange转发消息的策略有所区别
queue:消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连
接到这个队列将其取走。
binding:绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则。
Connection:网络连接,比如一个TCP连接
Channel:信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内的虚拟连接,AMQP命令都是通过信道发出去的,不管是发布消息
、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁TCP都是非常昂贵的开销,所以引入了信道的概念,以复用一条TCP连
接。
Consumer:消息消费者
virtual host:虚拟主机,表示一批交换器、消息队列和相关对象。
broker:消息队列服务器实体
--------------
RabbitMQ运行机制
AMQP中消息的路由过程和java开发者熟悉的JMS存在一些差别,AMQP中增强了Exchange和Binding的角色。生产者把消息发布到Exchange上,消息最终到达队列
被消费者接收,而Binding决定交换器的消息应该发送到那个队列。
producer->Exchanger->Binding->Queues-consumer;中间三个是在消息服务器中。
-----------
安装RabbitMQ:(windows版本)
需要先安装erlang,可以进入rabbitmq,里面会提示安装erlang,点击进去,可以找到需要按照的版本。需要配置erlang环境变量;
1、新建一个系统变量:变量名为ERLANG_HOME,变量值为安装Erlang的路径
2、将新建的系统变量添加在Path中:格式为%ERLANG_HOME%\bin
3、然后我们打开cmd输入erl查看是Erlan是否安装好、下图就表示已经安装好了
二、安装RabbitMQ
1、首先使用cmd进入sbin目录(我的sbin目录是:C:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.7\sbin)
2、然后输入: rabbitmq-plugins.bat enable rabbitmq_management 开启插件
3、还是在sbin目下:输入 rabbitmq-server 启动RabbitMQ服务
4、浏览器登录:localhost:15672访问RabbitMQ的后台管理页面(初始化用户名和密码都是guest)
--------------------
需要在Rabbit中设置Exchange,queue,routingkey;将queue绑定在Exchange
这样才能在程序中发送到指定的Exchange管理的queue中。不然发送的信息无法在RabbitMQ中寻找的到
-------------------
springboot整合rabbitMQ
1、在pom文件中加入rabbitMQ依赖
2、springboot会自动配置
自动配置类是rabbitautoConfiguration
有自动配置了连接工程ConnectionFactory
RabbitProperties封装了RabbitMQ配置
使用RabbitTemplate操作rabbitmq(发送和接收消息)
AmqpAdmin:RabbitMA系统管理功能组件
amqp:可以创建queue,exchange,binding
----------------------
给对象指定序列化格式为json
@Configuration public class MyRabbitMQConfig { @Bean public MessageConverter messageConverter(){ return new Jackson2JsonMessageConverter(); } }
public class RabbitTest { @Autowired private RabbitTemplate rabbitTemplate; /** * 点对点 */ @Test public void directTest(){ //Message需要自己构造一个,定义消息头和消息体 //rabbitTemplate.send(exchange, routingKey, message); //只需要传入对象,自动序列化发送给rabbit //rabbitTemplate.Send(exchange, routingKey, object); //Object指定的序列化是java的, //可以自己指定序列化json格式,配置MyRabbitMQConfig //rabbitTemplate.convertAndSend("lazy.direct","lazy.test","first"); Mapmap = new HashMap<>(); map.put("h1", "one"); map.put("h2", "tow"); rabbitTemplate.convertAndSend("lazy.direct","lazy.test",map); } /** * 接收消息 */ @Test public void receiveTest(){ Object object = rabbitTemplate.receiveAndConvert("lazy.test"); System.out.println(object.getClass()); System.out.println(object); } /** * 广播,不需要routingkey */ @Test public void sendMsg(){ Map map = new HashMap<>(); map.put("h1", "one"); map.put("h2", "tow"); rabbitTemplate.convertAndSend("lazy.fanout","",map); } } ------------ 消息队列使用场景:生产者发送消息,消费者获取指定消息;消费者需要监听指定的消息队列: 1、开启@EnableRabbit注解 @EnableRabbit //开启rabbit注解 @SpringBootApplication public class RabbitApplication{ public static void main(String[] args) { SpringApplication.run(RabbitApplication.class, args); } } 2、在消费者上标注注解,并指定队列名称:@RabbitListener(queue="lazy.fanout"),方法参数是接收指定的消息体的,方法参数一定是跟消息体一致的,否则 不能取出消息; @Service public class RabbitService { @RabbitListener(queues="lazy.fanout") public void receive(Map map){ System.out.println("接收消息:"+map); } } 注:public void receive(Map map,String str)是不行的,因为消息中只存储map;可以专门写监听类,将消息接收到,然后调用这个方法获取消息。 -------------- //使用AmqpAdmin创建、删除Exchange/queue/binding @Test public void amqpAdminTest(){ //创建exchange,这里的Exchange可以有TopicExchange,FanoutExchange等 //amqpAdmin.declareExchange(new DirectExchange("amqpAdmin.direct")); //创建队列new Queue("amqpAdmin.queue",true),第二个参数表示是否持久化 //amqpAdmin.declareQueue(new Queue("amqpAdmin.queue",true)); //在exchange绑定queue amqpAdmin.declareBinding(new Binding("amqpAdmin.queue", Binding.DestinationType.QUEUE, "amqpAdmin.direct", "amqpAdmin.lazy",null)); }