消息通信

来源:互联网 发布:js 字符串数组 编辑:程序博客网 时间:2024/06/06 05:28

生产者和消费者

  生产者(producer)创建消息,然后发送到代理服务器(RabbitMQ)。消息包含两部分:有效载荷(payload)标签(label)。有效载荷是你想要传输的数据,可以是任何内容,比如图片、json等,标签描述了有效载荷,用于确定消费者。
  消费者(consumer)订阅队列,RabbitMQ会把消息发给订阅队列的消费者,消费者只会收到有限载荷。  

信道

  客户端在接收消息或发送消息之前需要先创建一条信道(channel)。客户端在通过认证之后会打开TCP连接,然后会创建一条AQMP信道。信道是建立在TCP连接里的虚拟连接。不论是发送消息、订阅队列、接收消息,这些动作都是通过信道完成的。
  为什么不直接通过TCP连接发送AMQP命令呢?主要原因在于操作系统建立和销毁TCP会话代价非常昂贵,而每一个AMQP连接都有一个唯一的ID,在一条TCP连接上创建多少条信道是没有限制的。使用多个信道,多个线程可以同时共享连接,这意味着对请求的应答(一个发送信道)不会阻塞消费新的请求(另一个接收信道)
  

消息路由

  AMQP消息路由包括三个部分:交换器、队列和绑定。生产者把消息发布到交换器上,绑定决定了消息如何从交换器路由到特定的队列,消息最终到达队列,并被消费者接收。

两种订阅模式

  订阅有两种模式:basic.consume和basic.get,前者会持续订阅,后者则在接收一条消息之后就取消订阅。
  当队列拥有多个消费者时,队列收到的消息将以循环(round-robin)的方式发送给消费者。每条消息只会发送给一个订阅的消费者。

消息确认

  消费者接收到的每一条消息都必须进行确认,用于说明消息已被正确处理,防止客户端在收到消息之后因为异常情况而吞噬了消息。有两种确认方式:  

  1. 使用basic.ack命令显式地向RabbitMQ发送一个确认
  2. 在订阅到队列的时候就将auto_ack参数设置为true,一旦消费者接收消息,RabbitMQ会自动将其视为确认了消息。

如果消费者没有对消息进行确认,RabbtMQ会认为这条消息没有分发,然后重新发送给下一个订阅的消费者,同时RabbitMQ在得到确认之前不会给向消费者发送下一条消息。
  当有消息者接收到的消息无法被正确处理时,可以使用basic.reject命令表示拒绝。如果把该命令的参数requeue设置为true,该消息会发送给下一个消费者,如果设置为false,则会被移除。

创建队列

  生产者和消费者都可以通过basic.declare命令创建队列。消费者在一条信道上只可以订阅一个消息队列。创建和订阅队列都需要指定队列名称,如果创建队列时没有指定名称,RabbitMQ会分配一个随机名称并返回。
  创建队列可以设置以下队列属性:

  1. Exclusive:排他队列,如果一个队列被声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除。这里需要注意三点:其一,排他队列是基于连接可见的,同一连接的不同信道是可以同时访问同一个连接创建的排他队列的。其二,“首次”,如果一个连接已经声明了一个排他队列,其他连接是不允许建立同名的排他队列的,这个与普通队列不同。其三,即使该队列是持久化的,一旦连接关闭或者客户端退出,该排他队列都会被自动删除的。这种队列适用于只限于一个客户端发送读取消息的应用场景
  2. Auto-delete:自动删除,如果该队列没有任何订阅的消费者的话,该队列会被自动删除。这种队列适用于临时队列。

交换器和绑定

  发送消息时可以指定交换器和路由键。
  有四种交换器类型:direct、fanout、topic和headers,headers用于匹配AMQP消息的header而非路由键,性能较差。

direct交换器

  direct为默认路由器,名称为空字符串,当声明队列时,队列会以队列名为路由键加入默认路由器。direct路由器直接将消息路由到路由键相同的队列上。

fanout交换器

  当一条消息被发送到fanout交换器时,它会把消息投递给所有附加在此交换器上队列。

topic交换器

  topic交换器绑定的键值是类似“a.b.c”的形式,并且可以绑定多个键值,将队列绑定到topic交换器时,可以队列键值为任意一个键值,并且键值可以使用通配符点号*和井号#,*表示任意一段字符串(不包括点号),#表示匹配所有字符串(包括点号)。

原创粉丝点击