RabbitMQ学习记录 - Direct之Routing模式

(内容均来自RabbitMQ官网:https://www.rabbitmq.com/tutorials/tutorial-four-java.html

前面几篇学习了下RabbitMQ的"HelloWorld","WorkQueue","Publish/Subscribe",也大概的了解了RabbitMQ几个基本的组件:连接、通道、路由器、队列、生产者、消费者。这一篇学习下Direct中的Routing模式。

上一篇中我们使用的交换机的类型是fanout类型,RabbitMQ官方介绍的是fanout类型没有很大的灵活性,它只是一种无意识的广播。所有,我们在多个消费者的情况下,多个消费者收到的信息不管是数量、内容上都是形同的。

其实Direct模式和Publish/Subscribe没啥大的出入,不同点就是两点

  1. 指定交换机类型为:Direct(Publish/Subscribe模式中的路由器类型为fanout,fanout模式下的路由器即使你填写了routingkey也会被系统忽略掉)
  2. 发送信息时候指定routingKey,就只指定要发送到哪个队列中

图例

RabbitMQ官网的栗子说的是log日志的栗子。如果现实开发中有这么一个需求,系统中产生的error类型的日志我们需要落盘,info、error、warning等类型的需要输出到控制台

生产者

        这里在指定交换机类型为:direct,发送消息的时候用routingKey来区分我们需要路由器帮我们把消息投递到哪个队列。我们这里为了模拟error类型的消息和info类型的消息就简单的用i%3来区分

import com.booyue.tlh.utils.RabbitMQUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;

public class Producer {

    public static final String EXCHANGE_NAME = "logs_direct";

    public static final String LOGS_ERROR = "logs.error";
    public static final String LOGS_INFO = "logs.infor";

    public static final String MESSAGE = " Dicrect_Routing类型的消息";

    public static void main(String[] args) throws IOException {
        //获取一个连接
        Connection connection = RabbitMQUtils.getConnection();
        //获取一个通道
        Channel channel = connection.createChannel();
        /**
         * 声明一个交换机(运行完这一步,rabbitmq系统中就会创建一个名字和类型对应的)
         *  参数1:交换机名称
         *  参数2:交换机类型
         */
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");
        /**
         * 往“logs_direct”交换机里发送20条"{i} Hello RabbitMQ"的信息。指定routingKey
         */
        for (int i = 0; i < 10; i++) {
            if (i % 3 == 0) {
                //发送routingKey为logs.error的信息
                channel.basicPublish(EXCHANGE_NAME, LOGS_ERROR, null, (i + MESSAGE).getBytes());
            } else {
                //发送routingKey为logs.infor的信息
                channel.basicPublish(EXCHANGE_NAME, LOGS_INFO, null, (i + MESSAGE).getBytes());
            }
        }
    }
}

消费者01和消费者02

        这为了方便我就贴出了消费者01的代码,他们两个唯一不同的就是监听的routingKey和处理信息的业务逻辑不一样。消费者01监听的routingKey为:logs.error,消费者02监听的routingKey为:logs.info

import com.booyue.tlh.utils.RabbitMQUtils;
import com.rabbitmq.client.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

@Slf4j
public class Consumer01 {

    public static final String EXCHANGE_NAME = "logs_direct";

    public static final String LOGS_ERROR = "logs.error";

    public static void main(String[] args) throws IOException {
        //获取连接
        Connection connection = RabbitMQUtils.getConnection();
        //获取通道
        Channel channel = connection.createChannel();
        //声明一个交换机,名字为:logs_direct,类型为:direct
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");
        //创建一个临时队列(临时队列在客户端断开之后会自动删除,释放系统资源)
        String queueName = channel.queueDeclare().getQueue();
        //创建绑定关系
        channel.queueBind(queueName, EXCHANGE_NAME, LOGS_ERROR);

        /**
         * 接收消息
         *  参数1:队列名
         *  参数2:是否自动确认
         *  参数3:消息回调接口
         */
        channel.basicConsume(queueName, true, new DefaultConsumer(channel) {
            @SneakyThrows
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
                String message = new String(body, "utf-8");
                try {
                    //模拟完成业务逻辑的耗时
                    Thread.sleep(1000);
                } finally {
                    log.info("消费者1收到的信息:{}", message);
                }
            }
        });
    }
}

启动生产者和两个消费者,查看两个消费者收到的消息

        能看到我们根据不同的routingKey就能收到不用的信息。那么在现实场景中就能做不同的事情了

23:00:01.711 [pool-1-thread-6] INFO com.booyue.tlh.direct_routing.Consumer01 - 消费者1收到的信息:0 Dicrect_Routing类型的消息
23:00:02.712 [pool-1-thread-6] INFO com.booyue.tlh.direct_routing.Consumer01 - 消费者1收到的信息:3 Dicrect_Routing类型的消息
23:00:03.712 [pool-1-thread-6] INFO com.booyue.tlh.direct_routing.Consumer01 - 消费者1收到的信息:6 Dicrect_Routing类型的消息
23:00:04.713 [pool-1-thread-6] INFO com.booyue.tlh.direct_routing.Consumer01 - 消费者1收到的信息:9 Dicrect_Routing类型的消息



23:00:01.712 [pool-1-thread-7] INFO com.booyue.tlh.direct_routing.Consumer02 - 消费者2收到的信息:1 Dicrect_Routing类型的消息
23:00:02.713 [pool-1-thread-7] INFO com.booyue.tlh.direct_routing.Consumer02 - 消费者2收到的信息:2 Dicrect_Routing类型的消息
23:00:03.713 [pool-1-thread-7] INFO com.booyue.tlh.direct_routing.Consumer02 - 消费者2收到的信息:4 Dicrect_Routing类型的消息
23:00:04.714 [pool-1-thread-7] INFO com.booyue.tlh.direct_routing.Consumer02 - 消费者2收到的信息:5 Dicrect_Routing类型的消息
23:00:05.714 [pool-1-thread-7] INFO com.booyue.tlh.direct_routing.Consumer02 - 消费者2收到的信息:7 Dicrect_Routing类型的消息
23:00:06.715 [pool-1-thread-7] INFO com.booyue.tlh.direct_routing.Consumer02 - 消费者2收到的信息:8 Dicrect_Routing类型的消息

总结下

  1. Direct中的Routing模式和Publish/Subscribe模式的区别就是交换机的类型不一样。
    1. Direct中的Routing模式中的交换机类型为direct
    2. Publish/Subscribe模式中的交换机类型为fanout
  2. Direct中的Routing模式下,会根据routingKey的值将消息投递到不同的队列里面,从而实现消息的分类、筛选

猜你喜欢

转载自blog.csdn.net/qq_27062249/article/details/118558681