RabbitMQ
工作模式
消息队列,顾名思义就是将消息进行排队处理,后边来的消息进入不同的对列进行排队,然后消费者从队列中获取数据进行处理处理;
RabbitMQ的组件有生产者、消费者、交换机、队列、消息、路由等。他们之间的工作模式如下图所示:
- Exchange和fanout-Exchange:
- Direct-Exchange+路由消息模型:
- Topic-Exchange+路有消息模型:
(图片来源:https://blog.csdn.net/u013871100/article/details/82982235)
交换机模式
- 交换的常用的模式有Fanout-Exchange、Direct-Exchange,Topic-Exchange;
- Fanout-Exchange会忽略routingKey的绑定内容,它会将接收到的消息复制发送到每个绑定的每个队列(queue),而不会进行分流,它的作用相当于广播,对他的每个子队列都会发送消息;
- Driect-Exchange:交换机会与队列以一个routing-key绑定起来,发送消息后,交换机会按照routing-key将消息发送到相应的队列中去;如果没有队列接收该routing-key则,该条消息将被丢弃;
安装RabbitMQ服务
- 安装RabbitMQ之前需要先安装Erlang;
- Erlang下载地址:http://www.erlang.org/downloads
- 增加环境变量;
- RabbitMQ下载地址:https://www.rabbitmq.com/releases/rabbitmq-server/v3.6.15/rabbitmq-server-3.6.15.exe
- Linux在:这里查找相应的版本和安装包进行安装;
- 安装并配置环境变量 RABBITMQ_HOME;步骤:我的电脑右击->系统->高级系统设置->环境变量->系统变量->新建;
再将其加入到Path变量中:
SpringBoot整合RabbitMQ
引入pom依赖:
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
</dependency>
配置文件中作如下配置
生产者代码如下:
1. public class Send {
3. private final static String EXCHANGE_NAME = "test_exchange_direct";
5. public static void main(String[] argv) throws Exception {
6. // 获取到连接以及mq通道
7. Connection connection = ConnectionUtil.getConnection();
8. Channel channel = connection.createChannel();
10. //声明一个direct类型的exchange
11. channel.exchangeDeclare(EXCHANGE_NAME, "direct");
13. // 消息内容
14. String message = "删除商品, id = 1001";
//发送routing-key为delete的消息;
15. channel.basicPublish(EXCHANGE_NAME, "delete", null, message.getBytes());
16. System.out.println(" [x] Sent '" + message + "'");
18. channel.close();
19. connection.close();
20. }
21. }
消费者代码如下:
1. public class Recv {
3. private final static String QUEUE_NAME = "test_queue_direct_1";
5. private final static String EXCHANGE_NAME = "test_exchange_direct";
7. public static void main(String[] argv) throws Exception {
9. // 获取到连接以及mq通道
10. Connection connection = ConnectionUtil.getConnection();
11. Channel channel = connection.createChannel();
13. // 声明队列
14. channel.queueDeclare(QUEUE_NAME, false, false, false, null);
16. // 绑定队列到交换机 并接受routing-key为update的消息;
17. channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "update");
//banding队列到交换机,并接收 rou't
18. channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "delete");
20. // 同一时刻服务器只会发一条消息给消费者
21. channel.basicQos(1);
23. // 定义队列的消费者
24. QueueingConsumer consumer = new QueueingConsumer(channel);
25. // 监听队列,手动返回完成
26. channel.basicConsume(QUEUE_NAME, false, consumer);
28. // 获取消息
29. while (true) {
30. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
31. String message = new String(delivery.getBody());
32. System.out.println(" 前台系统: '" + message + "'");
33. Thread.sleep(10);
35. channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
36. }
37. }
38. }
- Topic-Exchange+路由消息模型是一个功能非常强大的交换机;它跟通配符结合可以代替上述两类交换机模型;
- 通配符‘’表示匹配一个关键字:如test. 可以与test.student匹配;却无法与test.student.list匹配;
- 通配符‘#’ 表示匹配0个或多个关键字;如上述例子,test.# 则可以与上述两个都可以匹配;
生产者代码如下:
1. public class Send {
3. private final static String EXCHANGE_NAME = "test_exchange_topic";
5. public static void main(String[] argv) throws Exception {
6. // 获取到连接以及mq通道
7. Connection connection = ConnectionUtil.getConnection();
8. Channel channel = connection.createChannel();
10. // 声明exchange
11. channel.exchangeDeclare(EXCHANGE_NAME, "topic");
13. // 消息内容
14. String message = "删除商品,id = 1001";
15. channel.basicPublish(EXCHANGE_NAME, "test.delete", null, message.getBytes());
16. System.out.println(" [x] Sent '" + message + "'");
18. channel.close();
19. connection.close();
20. }
21. }
消费者代码如下:
1. public class Recv2 {
3. private final static String QUEUE_NAME = "test_queue_topic_2";
5. private final static String EXCHANGE_NAME = "test_exchange_topic";
7. public static void main(String[] argv) throws Exception {
9. // 获取到连接以及mq通道
10. Connection connection = ConnectionUtil.getConnection();
11. Channel channel = connection.createChannel();
13. // 声明队列
14. channel.queueDeclare(QUEUE_NAME, false, false, false, null);
16. // 绑定队列到交换机并以"test.#"为路由键
17. channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "test.#");
19. // 同一时刻服务器只会发一条消息给消费者
20. channel.basicQos(1);
22. // 定义队列的消费者
23. QueueingConsumer consumer = new QueueingConsumer(channel);
24. // 监听队列,手动返回完成
25. channel.basicConsume(QUEUE_NAME, false, consumer);
27. // 获取消息
28. while (true) {
29. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
30. String message = new String(delivery.getBody());
31. System.out.println(" 搜索系统: '" + message + "'");
32. Thread.sleep(10);
34. channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
35. }
36. }
37. }
此处的队列则可以接收任何以test. 开头的任何消息;
参照地址:https://blog.csdn.net/u013871100/article/details/82982235