欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

rabbitmq中routingkey的作用说明

程序员文章站 2022-03-18 17:33:14
对于消息发布者而言它只负责把消息发布出去,甚至它也不知道消息是发到哪个queue,消息通过exchange到达queue,exchange的职责非常简单,就是一边接收发布者的消息一边把这些消息推到qu...

对于消息发布者而言它只负责把消息发布出去,甚至它也不知道消息是发到哪个queue,消息通过exchange到达queue,exchange的职责非常简单,就是一边接收发布者的消息一边把这些消息推到queue中。

而exchange是怎么知道消息应该推到哪个queue呢,这就要通过绑定queue与exchange时的routingkey了,通过代码进行绑定并且指定routingkey,下面有一张关系图,p(发布者) —> x(exchange) bindding(绑定关系也就是我们的routingkey) 红色代表着queue

rabbitmq中routingkey的作用说明

我们来看代码:

在消息的生产者端:

@component
public class rabbitordersender {
    //自动注入rabbittemplate模板类
    @autowired
    private rabbittemplate rabbittemplate;
    @autowired
    private brokermessagelogmapper brokermessagelogmapper;
    //回调函数: confirm确认
    final rabbittemplate.confirmcallback confirmcallback = new rabbittemplate.confirmcallback() {
        @override
        public void confirm(correlationdata correlationdata, boolean ack, string cause) {
            system.err.println("correlationdata: " + correlationdata);
            string messageid = correlationdata.getid();
            if(ack){
                //如果confirm返回成功 则进行更新
                brokermessagelogmapper.changebrokermessagelogstatus(messageid, constants.order_send_success, new date());
            } else {
                //失败则进行具体的后续操作:重试 或者补偿等手段
                system.err.println("异常处理...");
            }
        }
    };
    //发送消息方法调用: 构建自定义对象消息
    public void sendorder(order order) throws exception {
        // 通过实现 confirmcallback 接口,消息发送到 broker 后触发回调,确认消息是否到达 broker 服务器,也就是只确认是否正确到达 exchange 中
        rabbittemplate.setconfirmcallback(confirmcallback);
        //消息唯一id
        correlationdata correlationdata = new correlationdata(order.getmessageid());
        rabbittemplate.convertandsend("order-exchange", "order.abc", order, correlationdata);
    }
}

利用rabbittemplate(import org.springframework.amqp.rabbit.core.rabbittemplate;需要在pom.xml中导入amqp的依赖)的convertandsend方法就可以发送,这里order-exchange为交换机exchange,order.abc为routingkey,并没有指定对应消息需要发往哪个队列,还有指定消息回调。

在消息的消费者端:

@component
public class orderreceiver {
    //配置监听的哪一个队列,同时在没有queue和exchange的情况下会去创建并建立绑定关系
    @rabbitlistener(bindings = @queuebinding(
            value = @queue(value = "order-queue",durable = "true"),
            exchange = @exchange(name="order-exchange",durable = "true",type = "topic"),
            key = "order.*"
        )
    )
    @rabbithandler//如果有消息过来,在消费的时候调用这个方法
    public void onordermessage(@payload order order, @headers map<string,object> headers, channel channel) throws ioexception {
        //消费者操作
        system.out.println("---------收到消息,开始消费---------");
        system.out.println("订单id:"+order.getid());
        /**
         * delivery tag 用来标识信道中投递的消息。rabbitmq 推送消息给 consumer 时,会附带一个 delivery tag,
         * 以便 consumer 可以在消息确认时告诉 rabbitmq 到底是哪条消息被确认了。
         * rabbitmq 保证在每个信道中,每条消息的 delivery tag 从 1 开始递增。
         */
        long deliverytag = (long) headers.get(amqpheaders.delivery_tag);
        /**
         *  multiple 取值为 false 时,表示通知 rabbitmq 当前消息被确认
         *  如果为 true,则额外将比第一个参数指定的 delivery tag 小的消息一并确认
         */
        boolean multiple = false;
        //ack,确认一条消息已经被消费。不然的话,在rabbitmq首页会有unacked显示为未处理数1.
        channel.basicack(deliverytag,multiple);
    }
}

消费者需要指定监听的队列,routingkey,和exchage,如果在localhost:15672的rabbitmq的首页没有手动创建,@rabbitlistener会自动帮我们创建的并绑定关系。rabbitmq的routingkey还可以用来过滤从队列中取的的信息。

对 rabbitmq 基本理解(exchange queue binding-key routing-key)

一 exchange queue binding-key routing-key概念及相互间的关系

1.queue :存储消息的队列,可以指定name来唯一确定

2.exchange:交换机(常用有三种),用于接收生产者发来的消息,并通过binding-key 与 routing-key 的匹配关系来决定将消息分发到指定queue

  2.1 direct(路由模式):完全匹配 > 当消息的routing-key 与 exchange和queue间的binding-key完全匹配时,将消息分发到该queue

  2.2 fanout (订阅模式):与binding-key和routing-key无关,将接受到的消息分发给有绑定关系的所有队列(不论binding-key和routing-key是什么)

  2.3 topic (通配符模式):用消息的routing-key 与 exchange和queue间的binding-key 进行模式匹配,当满足规则时,分发到满足规则的所有队列

二 exchange queue binding-key routing-key的创建与使用

1. fanout

connectionfactory connectionfactory = new connectionfactory();
// 获取到tcp连接
connection connection = connectionfactory.newconnection();
 //从tcp连接中创建通道
 channel channel = connection.createchannel();
/ 声明exchange
channel.exchangedeclare(exchange_name, "fanout");
// 声明队列
channel.queuedeclare(queue_name, false, false, false, null);
channel.queuedeclare(queue_name2, false, false, false, null);
// 绑定队列到交换机
channel.queuebind(queue_name, exchange_name, "");
// 绑定队列到交换机 - aaa 是路由键3名称(其实这里无作用)
channel.queuebind(queue_name2, exchange_name, "aaa");

这样就创建好队列和交换机并且将它们绑定好了,只要交换机exchange_name收到消息就会分发给队列1和2

// 消息内容
string message = "qqqqqqqq";
channel.basicpublish(exchange_name, "aaa", null, message.getbytes()); // 这里路由键aaa有没有都一样,可以写任何值

2.不显式声明交换机时并且发送消息不指定交换机

则默认使用direct,并且声明队列时,不显式绑定队列与交换机,则队列以队列名为routing-key绑定到默认的direct交换机,发送消息不指定交换机时,则将消息发到默认的direct交换机

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

相关标签: rabbitmq routingkey