持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
Publish/Subscribe发布订阅模式
一次向多个消费者发送同一个消息,当很多微博用户都关注了A用户,当A发送动态是,微博就会给关注A的所有用户推送消息(类似kafka多个groupId的消息分发模式)。
这个机制是对Work Queues的一种补充,也就是把Producer与Consumer进行进一步解耦。Producer只负责发送消息,至于消息进入那个queue,由交换机(exchange)分配。
Producer示例代码:
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));
Consumer示例代码:
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String queueName = channel.queueDeclare().getQueue();
//将消费的目标队列绑定到exchange上。
channel.queueBind(queueName, EXCHANGE_NAME, "");
注意:
- 交换类型
fanout,只负责所有已绑定的队列上发送消息,不论你设置的路由键是什么。 - 交换机只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与
exchange绑定,那么消息会丢失。
Routing基于内容路由
有选择性的接收消息,例如我们构建一个简单的日志系统,我们能够向许多消费者发送日志消息,我们可以将error消息记录到日志文件,又同时可以将日志消息在控制台打印。
Producer示例代码:
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes("UTF-8"));
Cousumer示例代码:
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
channel.queueBind(queueName, EXCHANGE_NAME, routingKey1);
channel.queueBind(queueName, EXCHANGE_NAME, routingKey2);
channel.basicConsume(queueName, true, consumer);
注意:
- 交换类型
direct,会将绑定的路由键完全匹配的方式路由到指定的队列上。如果路由键不匹配,那么就不会发送到任何队列中去。
Topics主题
基于主题接收消息,在Routing模式下,我们有了新的要求,我们不仅仅是根据严重性来订阅,我们还需要根据日志来源来区分。
Producer示例代码:
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes("UTF-8"));
Cousumer示例代码:
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
channel.queueBind(queueName, EXCHANGE_NAME, routingKey1);
channel.queueBind(queueName, EXCHANGE_NAME, routingKey2);
channel.basicConsume(queueName, true, consumer);
注意:
*号表示匹配一个单词#号表示匹配0个或多个
RPC远程调用
远程调用是同步阻塞的调用远程服务并获取结果。
RPC并不是消息中间件的处理强项。毕竟消息队列机制很大程度上是为了缓冲同步RPC造成的瞬间洪峰。而RabbitMQ远程同步调用并没有带来什么,而且还有一些更优的选择。不建议使用。