RabbitMQ-routing

153 阅读2分钟

routing

在之前的导航中,我们创建了一个简单日志系统,我们能够将日志信息广播到很多接受者。

在本篇导航中,我们将为其添加一个特性-我们将使订阅消息的一个子集成为可能。例如,我们能够将错误信息定向写入错误日志文件,同时能够在控制台打印所有信息。

binding

在之前的例子中我们能够创建绑定,你可能会回想起这样的代码

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

绑定是交换和队列之间的关系。这可以简单地理解:队列对来自这个交换的消息感兴趣。

绑定可以使用额外的routingKey参数。为了避免与基本的发布参数混淆,我们将其称为绑定键。这就是我们如何键创建绑定的方法。

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

绑定键的意义取决于交换类型。我们之前使用的fanout交换机完全忽略了它的价值。

Direct exchange

我们之前使用的fanoutexchange,这并没有给我们多大的灵活性——它只能进行不需要动脑筋的广播。我们将用directexchange.消息可以传递到其绑定键bindingKey与消息的路由键routingkey完全匹配的队列

direct形式exchange

我们可以看到,这里面error可以发送到amqp.gen-S9b...amqp.gen-Ag1...队列中,而info和waring只能发送到amqp.gen-Ag1...队列中

Send.java

public class Send {
    private static final String EXCHANGE_NAME = "test_exchange_direct";

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtils.getConnection();
        // 创建channle
        Channel channel = connection.createChannel();
        // 声明exchange
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        String msg = "hello exchange direct";
        String routingKey = "error";
        channel.basicPublish(EXCHANGE_NAME, routingKey, null, msg.getBytes());

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

Rece1.java

public class Rece1 {
    private static final String EXCHANGE_NAME = "test_exchange_direct";
    private static final String QUEUE_NAME = "test_queue_direct1";

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"error");

        channel.basicQos(1);

        Consumer 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("rece1 recieve msg :" + msg);
                try{
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    System.out.println("rece1 done");
                    channel.basicAck(envelope.getDeliveryTag(),false);
                }
            }
        };
        channel.basicConsume(QUEUE_NAME,false,consumer);


    }
}

Rece2.java

public class Rece1 {
    private static final String EXCHANGE_NAME = "test_exchange_direct";
    private static final String QUEUE_NAME = "test_queue_direct1";

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"error");

        channel.basicQos(1);

        Consumer 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("rece1 recieve msg :" + msg);
                try{
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    System.out.println("rece1 done");
                    channel.basicAck(envelope.getDeliveryTag(),false);
                }
            }
        };
        channel.basicConsume(QUEUE_NAME,false,consumer);
    }
}

偶尔报错

队列绑定交换机时,routingKey是具有缓存机制的。我在写代码的时候,误操作了将队列都绑定了errorinfo,warning.我发现无法实现上述的效果,改了代码,但是还是无法解决。最后登录了RabbitMQ查看相关绑定。并使用的unbind功能。

8AFtBT.md.png