rabbitmq是一个erlang编写的消息引擎,支持amqp,mqtt等协议,提供web可视化管理工具。
基本概念:
- 交换器
生产者推送消息到交换器 - 队列
消费者从队列中拉取消息,生产者也可以直接推送消息到队列 - 路由键
绑定交换器和队列,配置交换器和队列之间的消息转发规则 - 消息
数据负载,包含数据信息 - 节点
一个消息服务器,完成生产者和消费者的连接以及消息的转发 - 集群
多个节点组合在一起,提供高可用的消息转发服务
消息转发的场景
- 一对一
一对一场景中,只需要声明一个队列即可,不需要交换器。生产者发送消息到队列,消费者从队列消费消息。
//生产者
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());//exchange为空,路由键作为队列名。
//消费者
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
- 一对多
一对多场景中,消费者有多个,同样,也只需要一个队列即可。生产者发送消息到队列,多个消费者从同一队列消费消息。自动回复模式下,消息采用轮询算法平均转发到每个消费者。也就是说,每个消费者只处理部分消息。
//生产者
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());//exchange为空,路由键作为队列名。
//消费者
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });//多个线程运行
- 订阅/发布
订阅/发布场景中,需要交换器+队列才能实现。消息不直接发送到队列,而是先发送到交换器,然后由交换器转发到与之绑定的队列,最后由队列上面的消费者的消费。
从交换器转发到队列的规则,由交换器类型决定,一共三种:fanout,direct,topic。我们把发送消息时指定的路由键成为【发送路由键】,把队列绑定交换器时指定的路由键称为【绑定路由键】。
fanout交换器:不管发送路由键是什么,会把发送给交换器的所有消息转发给与之绑定的队列。
direct交换器:只有发送路由键和绑定路由键完全相同时,交换器才会转发消息给队列。
tpoic交换器:只有发送路由键和绑定路由键符合主题匹配时,交换器才会转发消息给队列。主题是以.分割的字符串,由多个单词组成。其中#代表一个或多个单词,*代表不多不少一个单词。如果发送路由键是a.b.c,而绑定路由键是a.#,则匹配成功;如果是a.*则匹配失败。
需要注意的是,一个队列可以有多个【绑定路由键】,只要其中一个路由键匹配【发送路由键】,队列都会收到消息,从而队列上的消费者也会收到消息。
//声明交换器
channel.exchangeDeclare("logs", "fanout");
//声明三个队列并绑定到交换器
String queue1 = channel.queueDeclare().getQueue();
channel.queueBind(queue1 , "logs", "");//绑定路由键
String queue2 = channel.queueDeclare().getQueue();
channel.queueBind(queue2 , "logs", "");
String queue3 = channel.queueDeclare().getQueue();
channel.queueBind(queue3 , "logs", "");
//发送消息
channel.basicPublish( "logs", "", null, message.getBytes());//发送路由键
最终的结论是
- 同一队列上消费者只消费队列的部分消息。实现消息的【工作队列】模式。
- 同一交换器上满足转发规则的队列能收到交换器的所有消息。实现消息的【订阅发布】模式。