GinoBeFunny

AMQP学习小记

阅读《RabbitMQ实战》一书第二章理解消息通信的读书笔记。

思维导图

消费者和生产者

  • 生产者(producer)创建消息,然后发送到代理服务器(RabbitMQ)。
  • 消息包含两部分:有效载荷(payload)和标签(label);有效载荷就是你想要传输的数据(可以是任何格式的任何内容);标签描述了有效载荷,并且RabbitMQ用它来决定谁将获得消息的拷贝。
  • 消费者(consumer)连接到代理服务器上,并订阅到队列(queue)上;当消费者接收到消息时,它只得到消息的一部分:有效载荷(标签并没有随有效载荷一同传递)。
  • 信道(channel)建立在”真实的”TCP连接内的虚拟连接;不论是发布信息、订阅队列或是接收消息,都是通过信道完成的;不使用TCP连接主要是因为对于操作系统而言建立和销毁TCP会话非常昂贵的开销;在一条TCP连接上创建多少条信道是没有限制的。

队列

  • AMQP消息路由必须有三部分:交换器、队列和绑定。生成者把消息发布到交换器上;消息最终到达队列,并被消费者接收;绑定决定了消息如何从路由器到特定的队列。
  • 消费者和生产者都可以通过queue.declare命令来创建队列。queue-name:队列名称,不指定则随机生产;exclusive:设置为true则为私有队列,只有当前消费者可以订阅;auto-delete:设置为true时最后一个消费者取消订阅将自动移除队列;passive:队列不存在时返回错误。
  • 消费者通过两种方式从特定队列中接收消息:basic.consume(消息一到达队列就自动接收,推荐的方式)和basic.get(从队列里主动获取单条消息)。
  • 当一个队列拥有多个消费者时,队列接收到的消息将以循环(round-robin)的方式发给消费者。每条信息只会发送给一个订阅的消费者。
  • 消费者接收的每一条信息都必须进行确认,可以使用basic.ack命令显式确认或在订阅队列时将auto_ack参数设置为true(一旦接收就自动确认)。如果确认前与RabbitMQ断开连接,则会重新分发给下一个订阅的消费者;如果由于bug等忘记确认的话,RabbitMQ将不会发生新的消息。如果想明确拒绝新消息的话可以使用basic.reject命令(requeue参数为true则发送给其他消费者,为false则从队列中移除)。

交换器和绑定

  • 队列通过路由键(routing-key)绑定到交换器。如果消息不匹配任何绑定模式的话,将进入“黑洞”。
  • 四种类型的交换器:direct、fanout、topic和headers。direct类型以队列名称作为routing-key;fanout类型会把消息投递所有附件在此交换器上的队列;topic支持通过“*”和“#”符号匹配消费者发送的topic消息,并投递到指定队列。

多租户模式

  • 每个RabbitMQ服务器都能创建虚拟主机(vhost),其本质是一个mini版的RabbitMQ服务器,拥有自己的队列、交换器和绑定,同时也拥有自己的权限机制。
  • vhost之间是绝对隔离的。

持久化策略

  • 队列消息持久化需要满足三个条件:1.发布消息时设置投递模式为2(持久);2.发送到持久化的交换器(durable属性为true);3.到达持久化的队列(durable属性为true);
  • RabbitMQ通过持久化日志文件(记录在磁盘上)记录和恢复持久化消息;但是持久化日志会导致性能大幅降低,而且內建的集群对于这种方式工作得并不好。
  • 虽然AMQP 0-9-1规范支持了事务,但是使用事务会降低大约2-10倍的吞吐量,而且使生产者应用程序产生同步。RabbitMQ使用了“发送方确认模式”来保证消息投递,其最大的好处是它是异步的方式。
Gino Zhang wechat
扫一扫,关注我的微信公众号