详解RabbitMq之交换机

本文介绍了RabbitMQ中四种类型的交换机:fanout、direct、topic和headers的工作原理及使用示例。通过实例展示了如何配置队列和绑定键,帮助读者理解不同交换机的特点及其应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

rabbitMq有四种类型的交换机fanoutdirecttopicheaders

一、 不用交换机的队列

API介绍

/*
 * 创建队列
 * queue:队列名称
 * durable:队列持久化标志,ture为持久化
 * exclusive:排他队列
 * autoDelete:自动删除
 * arguments:Map类型,关于队列及队列中消息的详细设置
 */
channel.queueDeclare(queue, durable, exclusive, autoDelete, arguments)

arguments参数 请参考

生产者示例:

        //声明队列  
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        //发送10条消息,依次在消息后面附加1-10个点  
        for (int i = 6; i > 0; i--)  
        {  
            String message = "helloworld"+i;
            channel.basicPublish("", QUEUE_NAME,null, message.getBytes());  
        }   

消费者示例:

       //声明队列  
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);  
        QueueingConsumer consumer = new QueueingConsumer(channel);  
        // 指定消费队列  
        channel.basicConsume(QUEUE_NAME, true, consumer);  
        while (true)
        {  
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());
            doWork(message);
        }  

二 、fanout类型的交换机

1、消息与队列匹配规则:fanout类型交换机会将接收到的消息广播给所有与之绑定的队列。

如图所示:这种广播机制,生产者P只关心发给哪个交换机X

                                        消费者C只关心订阅了哪个队列

生产者示例:

 // 声明转发器和类型  
 channel.exchangeDeclare(EXCHANGE_NAME, "fanout" );     
 String message = "消息1";  
 // 往转发器上发送消息  
 channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes()); 

消费者示例:

channel.exchangeDeclare(EXCHANGE_NAME, "fanout");  
// 创建一个非持久的、唯一的且自动删除的队列  
String queueName = channel.queueDeclare().getQueue();  
// 为转发器指定队列,设置binding  
channel.queueBind(queueName, EXCHANGE_NAME, "");  
QueueingConsumer consumer = new QueueingConsumer(channel);  
// 指定接收者,第二个参数为自动应答,无需手动应答  
channel.basicConsume(queueName, true, consumer);  
while (true)  
{  
    QueueingConsumer.Delivery delivery = consumer.nextDelivery();  
    String message = new String(delivery.getBody());  
    doSomething(message);  
}

三 、direct类型的交换机

1、消息分发规则:消息会被推送至绑定键(binding key)和消息发布附带的选择键(routing key)完全匹配的队列。

生产者示例:

chanel.exchangeDeclare(EXCHANGE_NAME, "direct"); 
// 发布消息至转发器,指定routingkey  
chanel.basicPublish(EXCHANGE_NAME, "error", null, message1.getBytes()); 
chanel.basicPublish(EXCHANGE_NAME, "info", null, message2.getBytes()); 

消费者示例:

channel.exchangeDeclare(EXCHANGE_NAME, "direct");  
String queueName = channel.queueDeclare().getQueue();  
// 指定binding_key  
channel.queueBind(queueName, EXCHANGE_NAME, "error");   
channel.queueBind(queueName, EXCHANGE_NAME, "warning");
QueueingConsumer consumer = new QueueingConsumer(channel);  
channel.basicConsume(queueName, true, consumer);  
while (true)  
{  
    QueueingConsumer.Delivery delivery = consumer.nextDelivery();  
    String message = new String(delivery.getBody()); 
    doSomething(message);
}

四 、topic类型的交换机

1、消息分发规则:一个附带特殊的选择键将会被转发到绑定键与之匹配的队列中。可以简单理解为模糊匹配

四 、headers类型的交换机

1、消息分发规则:headers类型的交换机分发消息不依赖routingKey,是使用发送消息时basicProperties对象中的headers来匹配的。headers是一个键值对类型,发送者发送消息时将这些键值对放到basicProperties对象中的headers字段中,队列绑定交换机时绑定一些键值对,当两者匹配时,队列就可以收到消息。匹配模式有两种,在队列绑定到交换机时用x-match来指定,all代表定义的多个键值对都要满足,而any则代码只要满足一个就可以了。fanout,direct,topic exchange的routingKey都需要要字符串形式的,而headers exchange则没有这个要求,因为键值对的值可以是任何类型。

生产者示例:

//声明转发器和类型headers  
        channel.exchangeDeclare(EXCHANGE_NAME, ExchangeTypes.HEADERS,false,true,null);  
        String message = "消息1";  
        Map<String,Object> headers =  new Hashtable<String, Object>();  
        headers.put("aaa", "01234");  
        Builder properties = new BasicProperties.Builder();  
        properties.headers(headers);  
        // 指定消息发送到的转发器,绑定键值对headers键值对  
        channel.basicPublish(EXCHANGE_NAME, "",properties.build(),message.getBytes());

消费者示例:

 //声明转发器和类型headers  
        channel.exchangeDeclare(EXCHANGE_NAME, ExchangeTypes.HEADERS,false,true,null);  
        channel.queueDeclare(QUEUE_NAME,false, false, true,null);  

        Map<String, Object> headers = new Hashtable<String, Object>();  
        headers.put("x-match", "any");//all any  
        headers.put("aaa", "01234");  
        headers.put("bbb", "56789");  
        // 为转发器指定队列,设置binding 绑定header键值对  
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME,"", headers);  
        QueueingConsumer consumer = new QueueingConsumer(channel);  
        // 指定接收者,第二个参数为自动应答,无需手动应答  
        channel.basicConsume(QUEUE_NAME, true, consumer);  
        while (true) {  
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();  
            String message = new String(delivery.getBody());  
            System.out.println(message);  
        }   

### RabbitMQ 交换机类型详解 #### Direct Exchange Direct Exchange 是一种简单的路由机制,其中消息会根据指定的 routing key 被发送到对应的队列。如果某个队列绑定了特定的 routing key,则只有带有该 routing key 的消息才会被传递到这个队列[^3]。 ```python import pika connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() channel.exchange_declare(exchange='direct_logs', exchange_type='direct') severity = 'info' message = 'A info message' channel.basic_publish( exchange='direct_logs', routing_key=severity, body=message) print(f" [x] Sent {severity}:{message}") connection.close() ``` #### Topic Exchange Topic Exchange 提供了一种灵活的模式匹配功能,允许通过通配符来定义复杂的路由规则。这种交换机会依据消息中的 routing key 和绑定键之间的关系决定如何分发消息。它可以支持部分匹配以及完全匹配两种方式,因此非常适合用于多条件过滤的情况[^2]。 ```python import pika connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) channel = connection.channel() channel.exchange_declare(exchange='topic_logs', exchange_type='topic') routing_key = '*.critical.*' # Example of a pattern match rule. message = 'Critical error occurred.' channel.basic_publish( exchange='topic_logs', routing_key=routing_key, body=message) print(f"Sent '{message}' with routing key '{routing_key}'") connection.close() ``` #### Fanout Exchange Fanout Exchange 关心 routing key 或者 binding key,而是将接收到的所有消息广播至每一个与其关联的队列。这意味着无论消息的内容是什么样的形式或者携带什么样的属性标签,只要存在有效的连接路径就会无差别地复制一份副本给目标端点处理[^1]^. ```python import pika connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() channel.exchange_declare(exchange='logs', exchange_type='fanout') message = 'Broadcast this log entry.' channel.basic_publish(exchange='logs', routing_key='', body=message) print(" [x] Sent %r" % message) connection.close() ``` #### Headers Exchange Headers Exchange 则同于上述三种基于字符串作为关键字来进行寻址的方式;它是依靠附加于每条记录上的元数据字段集合——即所谓的头部(header),按照预设逻辑判断是否满足转发条件从而完成分配动作。这种方式更加抽象化也更少依赖具体文本表达式,因而可能带来更高的灵活性同时也增加了复杂度[^4]. 注意这里缺少实际代码示例因为headers exchange相对较少见且配置较为特殊需视具体情况而定。 --- ### 总结对比表: | 特性 | Direct | Topic | Fanout | Headers | |--------------|-------------|-------------|------------|------------| | **Routing Key** | Yes | Yes (Pattern Matching) | No | No | | **Binding Keys** | Exact Match Only | Pattern Supported | All Messages Broadcasted | Based on Header Values | | **Use Case** | Specific Routing Needed | Complex Filtering Required | Broadcasting to Multiple Consumers | Advanced Metadata-based Routing | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值