rabbitmq - 交换机

功能概述

交换机介于生产者和队列之间,生产者可以通过交换机,将消息分发到一个或多个队列上。

详细描述

张图画得非常形象,生产者和消费者之间,不是直接通过队列关联,还有交换机这一层。生产者将消息传递给交换机,交换机将消息分发到不同的队列,消费者选择队列读取消息。

因为多了一层交换机,生产者和消费者的关系变得非常灵活,生产者和队列之间,可以是1-n的关系,队列和消费者,也可以是1-n的关系,所以能适配非常多复杂的业务场景。

常用的交换机

详见源码:com.rabbitmq.client.BuiltinExchangeType

Direct Exchange ,

直连交换机,通过队列名称进行精准匹配。

Fanout Exchange

扇出交换机,消息会分配给每一个与交换机关联的队列。

Topic Exchange

主题交换机,通过模糊匹配的方式,将消息分配给命中的队列。

匹配规则:

*  (星号) 用来表示一个单词 (必须出现的)
#  (井号) 用来表示任意数量(零个或多个)单词

细节说明

  • 星号表示一个单词,而不是一个字母。
  • 当一个队列的绑定键为 "#"(井号) 的时候,这个队列将会无视消息的路由键,接收所有的消息。
  • 当 * (星号) 和 # (井号) 这两个特殊字符都未在绑定键中出现的时候,此时主题交换机等价于直连交换机。
  • 因此,通过主题交换机,也可以实现扇形交换机和直连交换机的功能。

举几个例子:

quick.orange.rabbit:可以匹配 *.orange.* 和*.*.rabbit
lazy.orange.elephant:可以匹配 *.orange.* 和lazy.#
lazy.pink.rabbit:可以匹配lazy.#和*.*.rabbit

Header Exchange

头交换机,根据消息头进行队列匹配。

其它

Dead Letter Exchange 死信交换机,不是 BuiltinExchangeType 中的选项,但是 rabbitmq 中有这个概念,可以再去了解了解。

测试用代码

消费者的代码,基本没什么变化,主要是生产者这边需要变动。

import com.rabbitmq.client.*;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeoutException;

/**
 * @author Mr.css
 * @version 2020-11-12 19:30
 */
public class ExchangePublish {
    /**
     * 队列名称
     */
    private static final String QUEUE_NAME = "queue_name";
    /**
     * 路由键,交换机会根据路由键,把消息推到队列,
     * 如果路由键与队列名称一致的情况,消息会被精准推送到同名的队列
     */
    private static final String ROUTING_KEY = "queue_name";
    /**
     * 交换机名称
     */
    private static final String EXCHANGE = "exchanges";

    public static void main(String[] args) {
        try {
            Connection connection = ConnectionUtil.getConnection();
            Channel channel = connection.createChannel();

            // 声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            // 声明交换机
            channel.exchangeDeclare(EXCHANGE, BuiltinExchangeType.DIRECT);
            // 声明一个绑定:队列绑定到交换机
            channel.queueBind(QUEUE_NAME,EXCHANGE,ROUTING_KEY);
            // 声明一个绑定:交换机绑定到交换机
            // channel.exchangeBind(EXCHANGE,EXCHANGE,ROUTING_KEY);

            int cnt = 10;
            while (cnt-- > 0) {
                String message = "This is simple queue:" + cnt;

                // 通过交换机,把消息发送到推送到队列中
                channel.basicPublish(EXCHANGE, ROUTING_KEY, null, message.getBytes(Charset.defaultCharset()));
                System.out.println("[send]:" + message);
            }

            channel.close();
            connection.close();
        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
        }
    }
}

消费者


import com.rabbitmq.client.*;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

/**
 * @author Mr.css
 * @version 2020-11-12 19:31
 */
public class ExchangeReceive {
    private static final String QUEUE_NAME = "queue_name";

    public static void main(String[] args) {
        try {
            Connection connection = ConnectionUtil.getConnection();
            Channel channel = connection.createChannel();
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);


            DefaultConsumer consumer = new DefaultConsumer(channel) {

                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
                                           byte[] body) {
                    //查看消息主体内容
                    String message = new String(body, StandardCharsets.UTF_8);
                    System.out.println("[receive]:" + message);
                }
            };

            // 设置为自动 ACK
            channel.basicConsume(QUEUE_NAME, true, consumer);
        } catch (IOException | ShutdownSignalException | ConsumerCancelledException | TimeoutException e) {
            e.printStackTrace();
        }
    }
}


交换机属性

前端管理页面,新增交换机的时候,可以看到这些属性,代码上,需要多个步骤完成。

  • 名称(name):exchange的名称;
  • 类型(type):可选值为 direct, headers, topic, fanout;
  • 持久化(durable):设置为 true,消息队列重启之后,交换机不会被删除;
  • 自动删除(Auto Delete):是否自动删除,默认是 No;启用时,绑定的交换机和队列,都接触绑定的时候,自动删除该交换机;
  • 内部使用(Internal): 是否内部使用,默认 NO。启用时,客户端不能直接投递消息到此交换器,只能由 rabbitmq 自己使用,一般用于 exchange 到 exchange 的绑定;
  • 其它属性(Arguments):一般设置为[],不需要。

posted on   疯狂的妞妞  阅读(106)  评论(0编辑  收藏  举报

(评论功能已被禁用)
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示