RabbitMQ消息队列的五种模式-路由模式

前言

上一个教程中我们构建了一个简单的日志记录系统。我们能够向许多接收者广播日志消息。

在本教程中,我们将向其中添加功能-我们将使仅订阅消息的子集成为可能。例如,我们将只能将严重错误消息定向到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息。

在前面的示例中,我们已经创建绑定,比如

channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,“”);

绑定是交换和队列之间的关系。可以简单地理解为:队列对来自此交换的消息感兴趣。绑定可以采用额外的routing Key参数,避免与basic_publish参数混淆,我们称为binding_key(绑定密钥)

直接交换

上一教程中的日志系统将所有消息广播给所有使用者。我们想要扩展它以允许根据邮件的严重性过滤邮件。例如,我们可能希望将日志消息写入磁盘的程序仅接收严重错误,而不会在警告或信息日志消息上浪费磁盘空间。我们使用的是fanout(扇型)交换,这种交换并没有给我们带来太大的灵活性-它只能进行无意识的广播。

我们将使用direct交换。direct交换背后的路由算法很简单-消息进入binding_key(绑定密钥)与消息的routing key(路由密钥)完全匹配的队列 。

为了说明这一点,请考虑以下设置:

 

在此设置中,我们可以看到绑定了两个队列的direct交换,第一个队列绑定键为orange,第二个绑定键为两个,一个绑定键为black,另一个绑定键为green。

在这种设置中,使用路由键orange发布到交换机的消息 将被路由到队列Q1。路由键为black 或为green 将转到Q2,所有其他消息将被丢弃。

多重绑定

在这种设置中,用相同的绑定密钥绑定多个队列也是完全可以的,类似为订阅模式,将消息广播到所有匹配的队列,同时发送到Q1 和 Q2中。

绑定类型

channel.exchangeDeclare(EXCHANGE_NAME,“direct”);

一、引入RabbitMQ的开发包

<dependency>
	<groupId>com.rabbitmq</groupId>
	<artifactId>amqp-client</artifactId>
	<version>3.6.6</version>
</dependency>

二、连接工具

package com.example.demo.util;

import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 消息队列连接工具
 *
 */
public class MQConnectionUtils {

    public static Connection connection() throws IOException, TimeoutException{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setPort(5672);

        return factory.newConnection();
    }
}

三、生产者

package com.example.demo.produce;

import com.example.demo.util.MQConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 路由模式 - 生产者
 *
 */
public class RouteProduce {

    private static final String EXCHANGE_NAME = "my_exchange_route";

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = MQConnectionUtils.connection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare(EXCHANGE_NAME, "direct");

        String msg = "", type = "";
        for (int i = 0; i < 20; i++){
            if ((i % 2) == 0){
                type = "error";
                msg = "hello,我是路由模式,消息类型为error:" + (i+1);

            }else {
                type = "info";
                msg = "hello,我是路由模式,消息类型为info:" + (i+1);
            }
            try {
                Thread.sleep(1000);
            }catch (Exception r){
                r.printStackTrace();
            }
            channel.basicPublish(EXCHANGE_NAME, type, null, msg.getBytes());
        }

        channel.close();
        connection.close();
    }
}

四、消费者

package com.example.demo.consume;

import com.example.demo.common.Constant;
import com.example.demo.util.MQConnectionUtils;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 路由模式 - 消费者1
 */
public class RouteConsume1 {
    
    private static final String ROUTE_QUEUE_INFO = "route_queue_info";
    
    private static final String EXCHANGE_NAME = "my_exchange_route";  

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection= MQConnectionUtils.connection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(ROUTE_QUEUE_INFO, false, false, false, null);

        // 1.队列名称 2.交换机名称 3.路由规则
        channel.queueBind(ROUTE_QUEUE_INFO, EXCHANGE_NAME, "info");
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                    throws IOException {
                String msg = new String(body,"UTF-8");
                System.out.println("消费者获取生产者消息:<" + msg +">");
            }
        };
        channel.basicConsume(ROUTE_QUEUE_INFO,true, consumer);
    }
}
package com.example.demo.consume;

import com.example.demo.common.Constant;
import com.example.demo.util.MQConnectionUtils;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 路由模式 - 消费者2
 *
 */
public class RouteConsume1 {
    
    private static final String ROUTE_QUEUE_ERROR = "route_queue_error";
    
    private static final String EXCHANGE_NAME = "my_exchange_route";  

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection= MQConnectionUtils.connection();
        Channel channel = connection.createChannel();

        channel.queueDeclare(ROUTE_QUEUE_ERROR, false, false, false, null);
        // 1.队列名称 2.交换机名称 3.路由规则
        channel.queueBind(ROUTE_QUEUE_ERROR, EXCHANGE_NAME, "error");
        
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                    throws IOException {
                String msg = new String(body,"UTF-8");
                System.out.println("消费者获取生产者消息:<" + msg +">");
            }
        };
        channel.basicConsume(ROUTE_QUEUE_ERROR,true, consumer);
    }
}

五、启动服务

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值