RabbitMQ 学习笔记 -- 05 路由模式

760 阅读4分钟

一、介绍

绑定是交换和队列之间的关系。绑定可以使用额外的绑定键参数。Spring AMQP 使用一个连贯的 API 来明确这种关系。我们将交换器和队列传递到 BindingBuilder ,并使用绑定键将队列“绑定到”交换器,如下所示

@Bean
public Binding binding(DirectExchange direct, Queue queue) {
    return BindingBuilder.bind(queue)
        .to(direct)
        .with("routingKey");
}

绑定键的意义取决于交换类型。我们以前使用的扇出交换器完全忽略了它的价值。

fanout 扇形交换机只会将接受到消息发送给直接绑定在它上面的队列,不能指定队列,所以需要 direct 直连交换机

direct 直连交换机需要配合路由键,绑定的键要精确匹配消息的路由键后,这个消息才能进入队列中

路由绑定
路由绑定

如上图,直连交换机 X 上绑定了2个队列。第一个队列使用的路由键是 orange ,第二个有两个路由键,blackgreen

把一个使用路由键为 orange 的消息推送到交换机上时,那么这个消息将会被路由到队列 Q1 上,消息使用的路由键是 black 或者 green 时将会被路由到 Q2。其余没有使用的路由键消息将会被丢弃。

伪扇形路由
伪扇形路由

并联绑定,采用这种路由方式,可以实现类似 fanout 交换机的功能

二、web 控制台操作

我们在 web 控制台界面创建一个直连型交换机, rabbit_exchange_direct

直连交换机 rabbit_exchange_direct
直连交换机 rabbit_exchange_direct

注意设置成 direct 模式,接下来创建两个队列 Q1,Q2,将其绑定在直连交换机 rabbit_exchange_dircet 上,并设上路由键

创建队列 Q1
创建队列 Q1
创建队列 Q2
创建队列 Q2
路由绑定
路由绑定

绑定队列,填写相应的路由键。Q1 绑定路由键 orange, Q2 绑定路由键 black 以及 green,最终为:

1575512837501
1575512837501

我们在交换机中发布消息,

发布消息
发布消息

这时候队列 Q1 接收到一条消息

效果
效果
队列读取消息
队列读取消息

三、代码方式

声明队列,交换机,以及绑定操作

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class config {
    @Bean
    public Queue queue1() {
        return new Queue("Q1");
    }
    @Bean
    public Queue queue2() {
        return new Queue("Q2");
    }
    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange("rabbit_exchange_direct");
    }
    // 路由绑定
    @Bean
    public Binding bindQ1() {
        String routingKey = "orange";
        return BindingBuilder.bind(queue1()).to(directExchange()).with(routingKey);
    }
    @Bean
    public Binding bindQ2_1() {
        String routingKey = "black";
        return BindingBuilder.bind(queue2()).to(directExchange()).with(routingKey);
    }
    @Bean
    public Binding bindQ2_2() {
        String routingKey = "green";
        return BindingBuilder.bind(queue2()).to(directExchange()).with(routingKey);
    }
}

消费者

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

@Component
public class consumer {
    @RabbitListener(queues = "Q1")
    public void receive(String msg, @Header(value = AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey) {
        System.out.println("队列 Q1 接收到消息:" + msg + ", 路由键为:" + routingKey);
    }
    @RabbitListener(queues = "Q2")
    public void receive2(String msg, @Header(value = AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey) {
        System.out.println("队列 Q2 接收到消息:" + msg + ", 路由键为:" + routingKey);
    }
}

@Header(value = AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey,可以将队列消息里所包含的头部消息映射出来,这里是读取到了队列消息的路由键

生产者

@Test
public void demo_04_Producer() {
    String exchange = "rabbit_exchange_direct";
    String routingKeyOrange = "orange";
    String routingKeyBlack = "black";
    String routingKeyGreen = "green";
    String msgOrange = "如果奇迹有颜色,那一定是橙色";
    String msgBlack = "如果黑化有颜色,那一定是黑色";
    String msgGreen = "如果爱情有颜色,那一定是绿色";
    rabbitTemplate.convertAndSend(exchange, routingKeyOrange, msgOrange);
    rabbitTemplate.convertAndSend(exchange, routingKeyBlack, msgBlack);
    rabbitTemplate.convertAndSend(exchange, routingKeyGreen, msgGreen);
}

输出

队列 Q1 接收到消息:如果奇迹有颜色,那一定是橙色, 路由键为:orange
队列 Q2 接收到消息:如果黑化有颜色,那一定是黑色, 路由键为:black
队列 Q2 接收到消息:如果爱情有颜色,那一定是绿色, 路由键为:green