RabbitMQ使用教程(五):路由模式—Routing

一、路由模式说明

前边我们学习了发布订阅模式,并且使用了fanout类型的交换机,使得每个消费者都会收到了消息,那么今天我们在此基础上再进一步探索:只接受一部分消息(差异化转发),这便是路由模式了。

那有了Routing模式,我们便可以改善我们的日志系统:根据严重级别作出不同的处理,将debug、info类型的日志打印到控制台,将error类型的日志保存到文件。

二、绑定关系与routingKey

还记得我们在使用发布、订阅模式的时候,使用了fanout交换机,并将队列与交换机进行了绑定:

channel.queueBind(queueName, EXCHANGE_NAME, "");

我们没有解释第三个参数,这个参数其实其实也是一个routingKey,我们在做发布、订阅的时候,将该参数设置为了”“,原因是fanout类型的交换机只会简单的为所有消费者发送消息,它会忽略这个参数!不管设置成什么参数,都没有任何影响。

该参数正好对应发送消息时指定的routingKey,也是之前被我们忽略了的”“,即下面的第二个参数

channel.basicPublish( "logs", "", null, message.getBytes());
fanout类型的交换机只会简单的为所有消费者发送消息,会忽略routingKey。

但是当我使用路由模式的时候,这个参数便会起到关键作用:只有对应的绑定routingKey的队列才会接收到消息,原理如下图:
这里写图片描述

队列Q1只能收到发布的routingKey为orange的消息,队列Q2只能收到发布的routingKey为black、green的消息。

当然,一个routingKey也可以被多个消费者指定,即多重绑定关系:
这里写图片描述
可以看到Q1、Q2队列都可以接受routingKey为black的发送消息。

三、日志系统改善

有了上面的原理,那么我们可以改善我们的日志系统了:

生产者-EmitLog.java:产生日志


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

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

public class EmitLog {
    private static final String EXCHANGE_NAME = "logs2";

    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");
        //debug日志
        for (int i = 1; i <= 3; i++) {
            String message = "debug_message" + i;
            channel.basicPublish(EXCHANGE_NAME, "debug", null, message.getBytes());
        }
        //info日志
        for (int i = 1; i <= 3; i++) {
            String message = "info_message" + i;
            channel.basicPublish(EXCHANGE_NAME, "info", null, message.getBytes());
        }
        //error日志
        for (int i = 1; i <= 3; i++) {
            String message = "error_message" + i;
            channel.basicPublish(EXCHANGE_NAME, "error", null, message.getBytes());
        }
        channel.close();
        connection.close();
    }
}

消费者1-ReceiveLog.java:处理debug类型的日志


import com.rabbitmq.client.*;

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

public class ReceiveLog1 {
    private static final String EXCHANGE_NAME = "logs2";

    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");
        String queueName = channel.queueDeclare().getQueue();
        channel.queueBind(queueName, EXCHANGE_NAME, "debug");
        Consumer consumer=new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                    throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(message);
            }
        };
        channel.basicConsume(queueName,true,consumer);
    }
}

消费者2-ReceiveLog2.java:处理info类型的日志


import com.rabbitmq.client.*;

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

public class ReceiveLog2 {
    private static final String EXCHANGE_NAME = "logs2";

    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");
        String queueName = channel.queueDeclare().getQueue();
        channel.queueBind(queueName, EXCHANGE_NAME, "info");
        Consumer consumer=new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                    throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(message);
            }
        };
        channel.basicConsume(queueName,true,consumer);
    }
}

消费者3-ReceiveLog3.java:处理error类型的日志


import com.rabbitmq.client.*;

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

public class ReceiveLog3 {
    private static final String EXCHANGE_NAME = "logs2";

    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");
        String queueName = channel.queueDeclare().getQueue();
        channel.queueBind(queueName, EXCHANGE_NAME, "error");
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                    throws IOException {
                String message = new String(body, "UTF-8");
                FileUtil.save(message);
                System.out.println("添加记录到文件!");
            }
        };
        channel.basicConsume(queueName,true,consumer);
    }
}

保存文件工具-FileUtil


import java.io.File;
import java.io.FileOutputStream;

public class FileUtil {
    public static void save(String content) {
        try {
            File dir = new File("D:/errors");
            if (!dir.exists()) {
                dir.mkdirs();
            }
            FileOutputStream fout = new FileOutputStream(dir +"/"+ content + ".txt");
            fout.write(content.getBytes());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

运行结果:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
下一篇,我们将来学习,更加个性化的模式:Topics

猜你喜欢

转载自blog.csdn.net/qq_35890572/article/details/81944308
今日推荐