在上一篇文章中,介绍了使用RabbitMQ的Hello World例子, 以及如何创建一个work queue。在work queue的例子中每条消息都只会被传递到一个work queue中。 在这篇文章中我们将会学习另一种完全不同的传递消息的方式——每条消息将会被传递给所有的consumer,这种模式一般被称为“发布/订阅”。
发布/订阅(Publish/Subscribe)
为了说明这种模式,我们将创建一个简单的log系统,它由两部分组成——第一部分负责发送log消息,第二部分负责接收并且将消息打印出来。 在我们的log系统中每个运行着的接收程序都会接收到消息,在这种方式下我们可以有一个consumer负责将log持久化到磁盘, 同时由另一个consumer来将log打印到控制台。本质上,发送log消息是对所有消息接收者的广播。
Exchange
在之前的部分我们都是通过queue来发送和接收消息,现在是时候来介绍RabbitMQ完整的消息模型了。先让我们来快速地回顾一下之前介绍过的几个概念:
producer是用户应用负责发送消息
queue是存储消息的缓冲(buffer)
consumer是用户应用负责接收消息
RabbitMQ的消息模型的核心思想是producer永远不会直接发送任何消息到queue中,实际上,在很多情况下producer根本不知道一条消息是否被发送到了哪个queue中。
在RabbitMQ中,producer只能将消息发送到一个exchange中。要理解exchange也非常简单,它一边负责接收producer发送的消息, 另一边将消息推送到queue中。exchange必须清楚的知道在收到消息之后该如何进行下一步的处理,比如是否应该将这条消息发送到某个queue中? 还是应该发送到多个queue中?还是应该直接丢弃这条消息等等。用官方文档上的一张图可以更清楚地了解RabbitMQ的消息模型。
RabbitMQ指南(中)
RabbitMQ中的exchange类型有这么几种:direct,topic,headers以及fanout。这一小节将会主要介绍最后一种类型——fanout。 使用RabbitMQ的client来创建一个fanout类型的exchange,命令为logs:
channel.exchangeDeclare(“logs”,”fanout”);
fanout类型的exchange非常简单,从名字也可以猜测出来,它会向所有的queue广播所有收到的消息。这正是我们的log系统需要的。
在之前的部分我们对exchange一无所知,但是我们仍然可以将消息发送到queue中,这是因为我们使用了默认的exchange,在代码中使用空字符串(“”)表示。
channel.basicPublish(“”, “hello”, null, message.getBytes());
第一个参数表示exchange的名字,使用空字符串表示使用默认的无名的exchange:如果有的话,消息将根据routingKey被发送到指定的queue中。
现在,可以将消息发送到之前已经声明过的exchange中
channel.basicPublish( “logs”, “”, null, message.getBytes());
临时队列
在之前的小节中使用queue都是指定了名字的(hello和task_queue),给queue命名是非常重要的,因为我们需要将的work