Spring Boot集成Rabbit MQ实战
一、Rabbit MQ简介
Rabbit MQ是基于Erlang语言开发的消息队列中间件系统,主要用来解决数据实时同步和响应问题。消息中间件产品比较常见的有ActiveMQ、Kafka、Rabbit MQ、RocketMQ等等。Rabbit MQ的优势是通过交换机绑定队列,消息支持持久化,服务器宕机消息仍然存在。并且Rabbit MQ支持ACK确认机制,消费确认,也支持分布式事务。
二、应用场景
Rabbit MQ支持多种语言客户端,比如C、Ruby、Java、Python、C#、PHP等主流语言。笔者曾经做过消息中转推送中心,基于Rabbit MQ的一个二次开发,将微信推送消息、短信平台、语音消息、邮件等消息推送封装在消息中心,通过Rabbit MQ开放接口,其他系统只需要按照接口协议封装实体类发送JSON数据,消息中心就能推送微信、短信、语音、邮件给用户,并且具有重试机制,不成功的消息记录到消息日志表中。
三、主要组件
虚拟主机:RabbitMQ支持权限控制,但是最小控制粒度为虚拟主机。一个虚拟主机可以包含多个交换机、队列、绑定。
交换机:交换机用来绑定队列,用于消息中间权限控制。
队列:队列用来存放消息,原理基于数据结构里面的队列。
然后通过将交换机和队列绑定在一起从而组成消息广播、消息存储与发送。
四、Spring Boot与Rabbit MQ整合搭建
新建一个Maven工程,与Spring Boot整合的Rabbit MQ在pom.xml中的配置为:
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-amqp org.springframework.boot spring-boot-starter-test test
在src/main/resources目录下新建application.yml指定项目端口号与连接Rabbit MQ配置,如下:
#访问端口server: port: 8482spring: application: name: ocai-core-rabbitmq session: store-type: none rabbitmq: host: 127.0.0.1 port: 5672 username: guest password: guest
新建com.ocai.core.mq.model包,在该包下新建实体User,代码为:
![056024874f68ae309a8e83d2c5e83f72.png](https://i-blog.csdnimg.cn/blog_migrate/8689339544371c0d2073f0724b4be3fb.jpeg)
新建com.hxdi.core.mq.rabbit包,包下新建RabbitConfig.java进行绑定队列,注意注解@Configuration
![85a81dbac21d23ea3d2fc097d320cd06.png](https://i-blog.csdnimg.cn/blog_migrate/1b3b02864e835429e480c1dee69d64cd.jpeg)
新建com.ocai.core.mq.rabbit.hello包,包下新建消息发送Bean组件,如图
![eae5ca23a76233a02a1a77ab9373ed9c.png](https://i-blog.csdnimg.cn/blog_migrate/ebe4324a40150a6165e89e54ed242b27.jpeg)
建立队列监听者,@RabbitListener(queues = "hello")表示监听hello这个队列
![426f210001754ea11269d41bd9c8abfa.png](https://i-blog.csdnimg.cn/blog_migrate/791a83f61fe09a79f07477ccbf29fdea.jpeg)
新建Junit测试工具类,通过调用HelloSender发送消息,如图
![9e007dd909a057c1c2837ddffd42ac10.png](https://i-blog.csdnimg.cn/blog_migrate/b678f943e75d492f09ddf3c78eef3d95.jpeg)
右键HelloTest运行测试工具,查看控制台结果
![8c1cd8a6b6d77d5ab08b07f1ad0b0236.png](https://i-blog.csdnimg.cn/blog_migrate/3e99ec04d158c51c30bdee8fc4a0d0ce.jpeg)
结果Sender为发送消息,Receiver为接收消息。
五、发送对象消息
新建ObjectSender,消息发送者,如图
![384adc62a3b272b9ad591015f454cd6f.png](https://i-blog.csdnimg.cn/blog_migrate/d9a8595e18da5d81632fd3c017c89e7a.jpeg)
新建ObjectReceiver绑定队列queues = "object"监听器,接收消息
![96651fd53cc3de35cf1edb753fd82423.png](https://i-blog.csdnimg.cn/blog_migrate/d29ef5c54a26f6d20bf13bec9c0b814e.jpeg)
新建Junit Test
![c91b82d7d0e6d77bf73a5ee5082c5e77.png](https://i-blog.csdnimg.cn/blog_migrate/cd4601d26aab069a541554febd2f5840.jpeg)
运行之后查看控制台
![c19a0eb906cbbaa254713f6a50a1ad0d.png](https://i-blog.csdnimg.cn/blog_migrate/d102abd8683673b57d5c855f23c9362a.jpeg)
接收对象
六、建立Topic交换机队列
建立TopicRabbitConfig.java,建立队列
![32afa55b4b871184c171dfa54b124485.png](https://i-blog.csdnimg.cn/blog_migrate/75be36fe982d2b72474003c03cb6dd44.jpeg)
建立交换机
![8a568d8b10979d255778839a47dee000.png](https://i-blog.csdnimg.cn/blog_migrate/8dcc82afbc1241877de98fa317342598.jpeg)
绑定交换机与队列并指定路由键
![9ced27ac2e0ce6696c7dd75ff47cfff0.png](https://i-blog.csdnimg.cn/blog_migrate/24d405b2ccc6bb671c1f5a496ea17d88.jpeg)
指定队列Sender,匹配topic.#路由键,并指定交换机topicExchange
![c6ae94f83364cb6a3177484b0a45cbc3.png](https://i-blog.csdnimg.cn/blog_migrate/4614b857bf183bb4b177f4b005ebd02c.jpeg)
匹配topic.message路由键
![6f9ab727ee2f4f416bd40bcf2f46a61c.png](https://i-blog.csdnimg.cn/blog_migrate/dfd8b45ec9131870073286de14ef08c3.jpeg)
匹配topic.#路由键
![cf3394928bd92ff3b8dee356d947cf83.png](https://i-blog.csdnimg.cn/blog_migrate/c20065cfa10aa2869c09b09a93a88ce3.jpeg)
接收队列queues = "topic.message"
![de2fa32076afc2c3a7f7e638a5c0c338.png](https://i-blog.csdnimg.cn/blog_migrate/c0f29dd9c7d484f7e3b151d23cf2b391.jpeg)
接收队列queues = "topic.messages"
![b449b471f68e07a3624f5d280ee6368a.png](https://i-blog.csdnimg.cn/blog_migrate/b4e7d350f58ae6f600cc94b615d3a412.jpeg)
建立Junit,代码如下:
![8bdcfa10a8c857aab3edb0d41524740a.png](https://i-blog.csdnimg.cn/blog_migrate/326437285cad91c8ade72fa165083657.jpeg)
运行topic查看队列接收情况
![7eb2fabcb58678595e785bff016c9186.png](https://i-blog.csdnimg.cn/blog_migrate/1b82157f1b20ef713605a2cd8f459a3d.jpeg)
由于绑定关系
![e96d920c76f968b2e9a2507b33b02a29.png](https://i-blog.csdnimg.cn/blog_migrate/6e1be7cc2aa5f96389d27ce839afa9db.jpeg)
因此是topic.messages这个队列接收到消息
![8c738cc73d82c4ebb59664e30c678b3a.png](https://i-blog.csdnimg.cn/blog_migrate/4bf433cc2a13e36e09d7aaa9ac9b6f41.jpeg)
回到Junit运行
![c4d430ac7611430ee4db7954786b471d.png](https://i-blog.csdnimg.cn/blog_migrate/bb4437dcee064b149c63ecedd425f3d5.jpeg)
运行结果
![b1826bcaa812567b637fe7cd9e365161.png](https://i-blog.csdnimg.cn/blog_migrate/7a087622adb4feec7d5b3b9f132f791c.jpeg)
可以看到queues = "topic.message"和queues = "topic.messages"这2个队列都收到了消息。
因为绑定关系
![4cc504662fc63edaa6ba4c7c9f8bff95.png](https://i-blog.csdnimg.cn/blog_migrate/99f53384b505131d753338a7394b3229.jpeg)
而发送者
![30409f4a2ad87086c025e341f987cff7.png](https://i-blog.csdnimg.cn/blog_migrate/c7e2e086dfa1184ce9c022669824f1e5.jpeg)
对于这2个路由键都符合
返回Junit运行
![235f00b62c1a1f4b11784680d932f64f.png](https://i-blog.csdnimg.cn/blog_migrate/a9dcf16f518a6dabcb083aac990752fb.jpeg)
运行结果
![6a3439678912ad4f116d1129e76588ce.png](https://i-blog.csdnimg.cn/blog_migrate/8fea1df6b553b0dd3484ae8e37756dcd.jpeg)
因为发送者
![68be6a2a218e070a77e3ecbed1992ee4.png](https://i-blog.csdnimg.cn/blog_migrate/fb388bbb5708a87f4c442b860679cdb7.jpeg)
topic.messages只匹配
![aadac25d5c75298c08a45ecb1fcbebb3.png](https://i-blog.csdnimg.cn/blog_migrate/f4225853ad264cdc810bc26684200c14.jpeg)
这个路由键,也就是
![7f86cd37e6ae774fa05c5502910d1bc7.png](https://i-blog.csdnimg.cn/blog_migrate/d35360a88dc08dde6f5ee8859d9e055b.jpeg)
这个队列
七、Fanout广播
广播FanoutRabbitConfig代码如下:
import org.springframework.amqp.core.Binding;import org.springframework.amqp.core.BindingBuilder;import org.springframework.amqp.core.FanoutExchange;import org.springframework.amqp.core.Queue;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class FanoutRabbitConfig { @Bean public Queue AMessage() { return new Queue("fanout.A"); } @Bean public Queue BMessage() { return new Queue("fanout.B"); } @Bean public Queue CMessage() { return new Queue("fanout.C"); } @Bean FanoutExchange fanoutExchange() { return new FanoutExchange("fanoutExchange"); } @Bean Binding bindingExchangeA(Queue AMessage, FanoutExchange fanoutExchange) { return BindingBuilder.bind(AMessage).to(fanoutExchange); } @Bean Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) { return BindingBuilder.bind(BMessage).to(fanoutExchange); } @Bean Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) { return BindingBuilder.bind(CMessage).to(fanoutExchange); }
广播交换机fanoutExchange绑定了3个队列
队列1:
![036aac1e8859001bf2d9fe7524192d70.png](https://i-blog.csdnimg.cn/blog_migrate/349cf6fd70c4133e2c869ab3c19a751e.jpeg)
队列2:
![0fa4d4a6bb7dade136a8d0cb5f06df15.png](https://i-blog.csdnimg.cn/blog_migrate/6c4bd0c645e8d3f15cd16e53b46cbc12.jpeg)
队列3:
![6a12cb995437c835c79aa50157c4e0de.png](https://i-blog.csdnimg.cn/blog_migrate/5450739c27db92015958c6dfc7d63842.jpeg)
队列发送者,广播交换机:
![b36a8cdd669f1da41c044d696f6c0d27.png](https://i-blog.csdnimg.cn/blog_migrate/cb9ab4ac8477a3e602a70a56889e9e93.jpeg)
Junit工具如下
![957b673b3f497bde842de7cc54238b29.png](https://i-blog.csdnimg.cn/blog_migrate/b6fddcce82f3afbe0877e3020b99ce30.jpeg)
运行Junit
![ffcd30e19a5776d45f0dcd5a9abe10de.png](https://i-blog.csdnimg.cn/blog_migrate/c761ec62af8e8ecff99c3d20ae56363c.jpeg)
可以看到广播交换机的3个队列都接收到了消息
八、Many队列
队列监听多次
接收者1:
![ed41a03206d51edbb393fc330a8f916f.png](https://i-blog.csdnimg.cn/blog_migrate/c8071bba122ab7a9ee66dfca5354feff.jpeg)
接收者2:
![79ca45719c7b0d91c4bdeb0697b3ed65.png](https://i-blog.csdnimg.cn/blog_migrate/38d93ce0992636e86a97c8218c73ef0d.jpeg)
发送者1:
![f0eb1a99966352d925dfbd0ad069ae15.png](https://i-blog.csdnimg.cn/blog_migrate/9eb0e0245ffe3471febae07ca2a6f7f3.jpeg)
发送者2:
![ad4907b706f9920f75a13464795b6cb1.png](https://i-blog.csdnimg.cn/blog_migrate/22e4c45827dd853da83ac6389daf7554.jpeg)
新建Junit:
![3bca00ec226bf42afbcd8c01facdd97c.png](https://i-blog.csdnimg.cn/blog_migrate/24fcd2b34603c0c8627a07d240286c94.jpeg)
运行manyToMany
![958d315fc33950f09b7cc59c21630515.png](https://i-blog.csdnimg.cn/blog_migrate/a02f6a04477907106e8a04bd10009983.jpeg)
可以看到队列交错运行,同一个队列对应关系Many To Many
以上就是分享的Spring Boot集成RabbitMQ实战,有机会分享一下自己的消息中转推送中心系统。