• 4.rabbitmq--路由模式


    rabbitmq--路由模式

    想象之前的订阅发布模式: 一个生产者,多个消费者,每一个消费者都有自己的一个队列,生产者没有将消息直接发送到队列,而是发送到了交换机,每个队列绑定交换机,生产者发送的消息经过交换机,到达队列,实现一个消息被多个消费者获取的目的。

    需要注意的是,如果将消息发送到一个没有队列绑定的exchange上面,那么该消息将会丢失,这是因为在rabbitMQ中exchange不具备存储消息的能力,只有队列具备存储消息的能力。

    但是如果想象下这样的一个场景:生产者有新增商品,修改商品,删除商品的消息,消费者包含前台系统和搜索系统,要求前台系统接收修改和删除商品的消息,搜索系统接收新增商品、修改商品和删除商品的消息。所以使用这种订阅模式实现商品数据的同步并不合理。因此我们介绍下一种模式:路由模式。

    这种模式添加了一个路由键,生产者发布消息的时候添加路由键,消费者绑定队列到交换机时添加键值,这样就可以接收到需要接收的消息。

     生产者:

     1 package com.maozw.mq.routing;
     2 
     3 import com.maozw.mq.config.RabbitConfig;
     4 import com.rabbitmq.client.Channel;
     5 import org.slf4j.Logger;
     6 import org.slf4j.LoggerFactory;
     7 import org.springframework.amqp.rabbit.connection.Connection;
     8 import org.springframework.amqp.rabbit.connection.ConnectionFactory;
     9 import org.springframework.beans.factory.annotation.Autowired;
    10 import org.springframework.web.bind.annotation.PathVariable;
    11 import org.springframework.web.bind.annotation.RequestMapping;
    12 import org.springframework.web.bind.annotation.RestController;
    13 
    14 import java.io.IOException;
    15 import java.util.concurrent.TimeoutException;
    16 
    17 import static org.apache.log4j.varia.ExternallyRolledFileAppender.OK;
    18 
    19 /**
    20  * work 模式
    21  * 两种分发: 轮询分发 + 公平分发
    22  * 轮询分发:消费端:自动确认消息;boolean autoAck = true;
    23  * 公平分发: 消费端:手动确认消息 boolean autoAck = false; channel.basicAck(envelope.getDeliveryTag(),false);
    24  *
    25  * @author MAOZW
    26  * @Description: ${todo}
    27  * @date 2018/11/26 15:06
    28  */
    29 @RestController
    30 @RequestMapping("/routing")
    31 public class RoutingProducer {
    32     private static final Logger LOGGER = LoggerFactory.getLogger(RoutingProducer.class);
    33     @Autowired
    34     RabbitConfig rabbitConfig;
    35 
    36 
    37     @RequestMapping("/send")
    38     public String send() throws IOException, TimeoutException {
    39         Connection connection = null;
    40         Channel channel= null;
    41         try {
    42             ConnectionFactory connectionFactory = rabbitConfig.connectionFactory();
    43             connection = connectionFactory.createConnection();
    44             channel = connection.createChannel(false);
    45 
    46             /**
    47              * 申明交换机 以及type
    48              */
    49             channel.exchangeDeclare(RabbitConfig.EXCHANGE_ROUTE,"direct");
    50 
    51             /**
    52              * 发送消息
    53              * 每个消费者 发送确认消息之前,消息队列不会发送下一个消息给消费者,一次只处理一个消息
    54              * 自动模式无需设置下面设置
    55              */
    56             int prefetchCount = 1;
    57             channel.basicQos(prefetchCount);
    58 
    59             String Hello = ">>>> Hello EXCHANGE_ROUTE <<<<";
    60             for (int i = 0; i < 5; i++) {
    61                 String message = Hello + i;
    62                 if (i == 3){
    63                     channel.basicPublish(RabbitConfig.EXCHANGE_ROUTE, RabbitConfig.ROUTINGKEY_A, null, message.getBytes());
    64                 }else{
    65                     channel.basicPublish(RabbitConfig.EXCHANGE_ROUTE, RabbitConfig.ROUTINGKEY_B, null, message.getBytes());
    66                 }
    67                 LOGGER.info("生产消息: " + message);
    68             }
    69             return "OK";
    70         }catch (Exception e) {
    71 
    72         } finally {
    73             connection.close();
    74             channel.close();
    75             return OK;
    76         }
    77     }
    78 }

    消费者1 

     1 package com.maozw.mq.routing;
     2 
     3 import com.maozw.mq.config.RabbitConfig;
     4 import com.rabbitmq.client.AMQP;
     5 import com.rabbitmq.client.Channel;
     6 import com.rabbitmq.client.DefaultConsumer;
     7 import com.rabbitmq.client.Envelope;
     8 import org.slf4j.Logger;
     9 import org.slf4j.LoggerFactory;
    10 import org.springframework.amqp.rabbit.connection.Connection;
    11 import org.springframework.amqp.rabbit.connection.ConnectionFactory;
    12 
    13 import java.io.IOException;
    14 
    15 /**
    16  * @author MAOZW
    17  * @Description: ${todo}
    18  * @date 2018/11/26 15:06
    19  */
    20 
    21 public class RoutingConsumer {
    22     private static final Logger LOGGER = LoggerFactory.getLogger(RoutingConsumer.class);
    23 
    24     public static void main(String[] args) throws IOException {
    25         ConnectionFactory connectionFactory = RabbitConfig.getConnectionFactory();
    26         Connection connection = connectionFactory.createConnection();
    27         Channel channel = connection.createChannel(false);
    28         /**
    29          * 创建队列申明
    30          */
    31         boolean durable = true;
    32         channel.queueDeclare(RabbitConfig.QUEUE_ROUTE, durable, false, false, null);
    33         /**
    34          * 绑定队列到交换机
    35          */
    36         channel.queueBind(RabbitConfig.QUEUE_ROUTE, RabbitConfig.EXCHANGE_ROUTE,RabbitConfig.ROUTINGKEY_A);
    37 
    38         /**
    39          * 改变分发规则
    40          */
    41         channel.basicQos(1);
    42         DefaultConsumer consumer = new DefaultConsumer(channel) {
    43             @Override
    44             public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    45                 super.handleDelivery(consumerTag, envelope, properties, body);
    46                 System.out.println("[1] 接口数据 : " + new String(body, "utf-8"));
    47                 try {
    48                     Thread.sleep(100);
    49                 } catch (InterruptedException e) {
    50                     e.printStackTrace();
    51                 } finally {
    52                     System.out.println("[1] done!");
    53                     //消息应答:手动回执,手动确认消息
    54                     channel.basicAck(envelope.getDeliveryTag(),false);
    55                 }
    56             }
    57         };
    58         //监听队列
    59         /**
    60          * autoAck 消息应答
    61          *  默认轮询分发打开:true :这种模式一旦rabbitmq将消息发送给消费者,就会从内存中删除该消息,不关心客户端是否消费正常。
    62          *  使用公平分发需要关闭autoAck:false  需要手动发送回执
    63          */
    64         boolean autoAck = false;
    65         channel.basicConsume(RabbitConfig.QUEUE_ROUTE,autoAck, consumer);
    66     }
    67     
    68 }
     1 package com.maozw.mq.routing;
     2 
     3 import com.maozw.mq.config.RabbitConfig;
     4 import com.rabbitmq.client.AMQP;
     5 import com.rabbitmq.client.Channel;
     6 import com.rabbitmq.client.DefaultConsumer;
     7 import com.rabbitmq.client.Envelope;
     8 import org.slf4j.Logger;
     9 import org.slf4j.LoggerFactory;
    10 import org.springframework.amqp.rabbit.connection.Connection;
    11 import org.springframework.amqp.rabbit.connection.ConnectionFactory;
    12 
    13 import java.io.IOException;
    14 
    15 /**
    16  * @author MAOZW
    17  * @Description: ${todo}
    18  * @date 2018/11/26 15:06
    19  */
    20 
    21 public class RoutingConsumer2 {
    22     private static final Logger LOGGER = LoggerFactory.getLogger(RoutingConsumer2.class);
    23 
    24     public static void main(String[] args) throws IOException {
    25         ConnectionFactory connectionFactory = RabbitConfig.getConnectionFactory();
    26         Connection connection = connectionFactory.createConnection();
    27         Channel channel = connection.createChannel(false);
    28         /**
    29          * 创建队列申明
    30          */
    31         boolean durable = true;
    32         channel.queueDeclare(RabbitConfig.QUEUE_ROUTE2, durable, false, false, null);
    33         /**
    34          * 绑定队列到交换机
    35          */
    36         channel.queueBind(RabbitConfig.QUEUE_ROUTE2, RabbitConfig.EXCHANGE_ROUTE,RabbitConfig.ROUTINGKEY_B);
    37 
    38         /**
    39          * 改变分发规则
    40          */
    41         channel.basicQos(1);
    42         DefaultConsumer consumer = new DefaultConsumer(channel) {
    43             @Override
    44             public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    45                 super.handleDelivery(consumerTag, envelope, properties, body);
    46                 System.out.println("[2] 接口数据 : " + new String(body, "utf-8"));
    47                 try {
    48                     Thread.sleep(100);
    49                 } catch (InterruptedException e) {
    50                     e.printStackTrace();
    51                 } finally {
    52                     System.out.println("[2] done!");
    53                     //消息应答:手动回执,手动确认消息
    54                     channel.basicAck(envelope.getDeliveryTag(),false);
    55                 }
    56             }
    57         };
    58         //监听队列
    59         /**
    60          * autoAck 消息应答
    61          *  默认轮询分发打开:true :这种模式一旦rabbitmq将消息发送给消费者,就会从内存中删除该消息,不关心客户端是否消费正常。
    62          *  使用公平分发需要关闭autoAck:false  需要手动发送回执
    63          */
    64         boolean autoAck = false;
    65         channel.basicConsume(RabbitConfig.QUEUE_ROUTE2,autoAck, consumer);
    66     }
    67 }
  • 相关阅读:
    U1. 广度优先搜索(BFS)和 广度优先搜索(DFS)
    C5. Spring 服务的注册与发现(Spring Cloud Eureka)
    S3. Android 消息推送
    S2. Android 常用控件
    S12. Android 检查更新功能实现
    S1. Android 功能大全
    B9 Concurrent 重入锁(ReentrantLock)
    117.dom2事件
    106.事件的传播机制
    105.事件对象及兼容处理
  • 原文地址:https://www.cnblogs.com/Mao-admin/p/10034095.html
Copyright © 2020-2023  润新知