RabbitMQ 使用 | 第三篇:发布/订阅模式

RabbitMQ 使用 | 第三篇:发布/订阅模式

大部分内容仅仅对官方教程进行了翻译,有些内容为了更简便进行了调整

在上两篇文章中,介绍了的RabbitMQ的消息收发模型都是发送的消息只能订阅一次,意思就是说,发布了消息之后,每一条消息只有一个订阅者能接收到该消息。发布/订阅模式是指发送消息,到某个队列,所有订阅了该队列的接受者都能接收到全部的消息。(类似观察者模式)

简介:

RabbitMQ中,所有生产者提交的消息都由Exchange来接受,然后Exchange按照特定的策略转发到Queue进行存储
RabbitMQ提供了四种Exchangefanout,direct,topic,header

本节用到的Exchangefanout,所以针对这种进行解释

  • fanout这种模式不需要指定队列名称,需要将Exchangequeue绑定,他们之间的关系是‘多对多’的关系
    任何发送到fanout Exchange的消息都会被转发到与该Exchange绑定的queue上面。

发布/订阅模式就是是基于fanout Exchange实现的。

回顾一下之前使用的声明和发送消息代码:

channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String message = "Hello world";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());

在前面的教程中,我们对Exchange一无所知,但是仍然能够发送消息,这是我们在使用默认的Exchange,我们用空字符串来标识 “”

channel.basicPublish("", QUEUE_NAME, null, message.getBytes());

第一个参数是Exchange的参数,这里使用了空字符串,标识使用默认的Exchange,消息会发送到指定的QUEUE_NAME

如果使用fanout Exchange需要改为以下代码:

//声明一个名为logs的类型为fanout的Exchange
channel.exchangeDeclare("logs", "fanout");
String message = "Hello World."
//对这个Exchange发送消息
channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());

接收的时候:


//声明一个名为logs的类型为fanout的Exchange
channel.exchangeDeclare("logs", "fanout");
//创建并获取一个队列名称
String queueName = channel.queueDeclare().getQueue();
//绑定队列到Exchange
channel.queueBind(queueName,”logs“, "");

System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

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(" [x] Received '" + message + "'");
    }
};
channel.basicConsume(queueName, true, consumer);
}

以上就是使用fanout Exchange的代码,全部代码贴出如下:

发送端:

public class Publisher {
    private static final String EXCHANGE_NAME = "logs";

    public static void main(String[] argv)
            throws java.io.IOException, TimeoutException {

        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");

        String[] messages =  new String[]{"First message.", "Second message..",
                "Third message...", "Fourth message....", "Fifth message....."};
        for (String message : messages) {
            channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
            System.out.println("[x] Sent '" + message + "'");
        }
        channel.close();
        connection.close();
    }
}

接收端:

public class Subscriber {
    private static final String EXCHANGE_NAME = "logs";

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
        String queueName = channel.queueDeclare().getQueue();
        channel.queueBind(queueName, EXCHANGE_NAME, "");

        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        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(" [x] Received '" + message + "'");
            }
        };
        channel.basicConsume(queueName, true, consumer);
    }
}

此时启动顺序有点需要注意,要先启动接收端,再启动发送端,我们启动3个Subscriber,然后运行Publisher。这个时候你会发现在Publisher控制台输出:

[x] Sent 'First message.'
[x] Sent 'Second message..'
[x] Sent 'Third message...'
[x] Sent 'Fourth message....'
[x] Sent 'Fifth message.....'

Process finished with exit code 0

然后在3个Subscriber控制台都能看到输出:

 [*] Waiting for messages. To exit press CTRL+C
 [x] Received 'First message.'
 [x] Received 'Second message..'
 [x] Received 'Third message...'
 [x] Received 'Fourth message....'
 [x] Received 'Fifth message.....'

这证明了每个Subscriber都能接受到完整的消息。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值