RabbitMQ简介下

队列

在AMQP模型中的队列和其它的消息和任务队列系统非常相似:她们存储用于被应用程序消费的消息。并且和exchange共享一些属性,但是也有自己额外的属性:

  • 名字(Name)
  • 持久性(Durable):当broker重启的时候,队列仍然存活
  • 互斥性(Exclusive):只适用于被一个连接使用时,当连接关闭,队列删除
  • 自动删除(Auto-delete):当最后一个消费者取消订阅,队列将被删除
  • 参数(Arguments): 一些broker使用她来实现附加功能,比如消息TTL

队列要使用必须先声明,声明一个不存在的队列将创建这个队列,如果声明一个属性和名字与原有队列一样的队列,将不会产生什么影响。如果队列的属性不一样就会使用406码(PRECONDITION_FAILED)抛出一个channel级别的异常。

队列名字

应用可以选择一个队列的名字,也可以要broker生成一个队列的名字。队列的名字可以是255个字符的UTF-8。传空字符串给队列的名字参数,broker将产生一个唯一的名字给你的队列。在同一个channel上使用一个空字符串作为队列名参数调用子类的方法可能得到相同的队列名。这是由于channel记住了最新产生的队列名。

以“amq.”开始的队列名,是留给broker内部使用的保留队列名。以amq.定义一个队列名将获得一个channel级别的异常,异常码为403(ACCESS_REFUSED)

队列的持久性

持久化队列会持久化到磁盘上,即使broker重启。会持久化队列叫做临时性队列。不是所有的场景需要队列持久化的。

持久化队列并不意味着消息也具有持久化的功能。如果一个broker挂了,再起来,持久化队列将重新定义,但是只有持久化的消息会被恢复。

绑定(Bindings)

他是exchenge把消息投递到去队列的规则。告诉一个exchange E把消息投递到队列Q,Q被绑定到E上。某些exchange将选择路由key作Bindings。

使用路由key是为了选择确定的信息发布到绑定的队列。换而言之,路由key的动作就像是一个过滤器。

比如:

  • 队列就像你在纽约的目的地
  • 交换器就像是JFK的机场
  • Bindings就是JFK到达目的地的路径,可以有很多路到达这里

使用这种分层的架构,使不可能的路由场景或者用直接发送到队列非常难实现场景成为可能,并且避免了应用开发人员不得不做的某些重复工作。

如果AMQP的信息不能投递到任何队列(比如,由于没有bindings到exchange上),她可以删除信息也可以返回给发送者,完全取决于发送者消息属性的设置。

消费者(Consumers)

存储的信息是没有用的,除非应用能消费它们,在AMQP 0-9-1模型中,应用消费消息有两种方式:

  1. 有消息就推送给他们(“push API”)
  2. 自己按需拉取消息(“pull API”)

使用“push API”,应用必须告诉她想从某个特定的队列中消费消息。当她这样做,我们通常说它们注册了一个消费,或者简单的说,他们订阅了一个队列。可能有不止一个的消费者消费每一个队列,也可能有消费者独占一个队列(当她在消费时,排斥其它的所有消费者)。
每一个消费者或者叫订阅者,都有一个叫消费标签的东东来标实自己。它可以用来取消订阅消息,消费者标示只能是字符串。

消息确认(Message Acknowledgements)

消费和处理消息的应用很有可能处理失败或者发生某些冲突。也可能是网络的问题。这些问题导致AMQP的broker什么时候该从队列中移走消息?AMQP规范规定broker有两个选择可以做这个事:

  1. 在broker发送信息给应用之后(可以使用basic.deliver或者basic.get-ok两个AMQP方法)
  2. 应用返回一个确认信息(使用basic.ack的AMQP方法)

第一种方式叫做自动确认模式,后面一种叫做手动确认模式。在手动确认模式中,应用程序选择何时发送确认信息。可以是在收到消息之后,也可以是保存信息到数据库之后,也可以是所有步骤都执行之后。
如果消费者死去而没有发送任何的确认信息,broker将重新发送消息给另一个消费者,或者如果没有一个消费是可用的,broker将一直等待,直到至少有一个消费者注册到相同的队列,他将把消息发送给这个注册者。

驳回消息

消费者处理接收的消息,执行过程中可能会失败。消费者可以通过驳回信息的方式告诉broker自己的执行过程失败了。当驳回一个信息时,消费者可以要broker丢弃或者重新加载信息到队列。当只有一个消费者注册在队列上时,注意不要不合理的驳回产生驳回,再入列,在消费的死循环!

否定确认信息

消息可以使用basic.reject的AMQP方法驳回。但是有限制:没有办法驳回已经确认的信息。但是,如果你使用RabbitMQ,将有解决方案,RabbitMQ提供了一个AMQP 0-9-1的去扩展叫否定确认或者叫做否定回答。

预抓信息

当多个消费者共享一个队列的时候,指定一个队列在发送下一个确定消息时可以接收多少消息是很有用的。它可以被用作简单的负载均衡技术,或者提高批量消息发布的吞吐量。

注意:RabbitMQ只提供channel级别的prefetch-count,不提供connection或者基本个数的预抓

消息的属性和装载量(Message Attributes and Payload)

AMQP模型的消息有属性,一些普通的属性是AMQP0-9-1明确指定的,开发者没有必要去管他们具体的名字。例如:

  • Content-type
  • Content encoding
  • Routing key
  • Delivery mode(persistent or not)
  • Message priority
  • Message publishing timestamp
  • Expriation period
  • Publisher application id

一些属性要被broker用到,一些属性是可选的以header的形式为人所知,就像HTTP里面的X-Header信息。消息属性在消息被发送时被定义。

AMQP消息也有payload(携带数据的),broker会把他们当成透明的字符数组。她不会修改和监视他们。没有payload只有一些属性的消息是可以存在的。一般采用JSON,Thrift,网关缓存和消息包的方式序列化结构化数据放在payload中。AMQP一般使用content-type和content-encoding字段的值传递与之相关的信息,这两个属性只有在转换的时候才用到。

连接(Connections)

AMQP连接一般是长连接,AMQP饰应用级的使用TCP的可靠连接传递信息。连接可以用TLS(SSL)来授权。当连接不在连接broker应该优雅的关闭连接而不是突然的关闭。

渠道(Channels)

有些应用需要连接broker的多个连接。但是许多的TCP连接在同一时间被打开,这样会导致系统资源的占用,防火墙也不好配置,因此是不受欢迎的。AMQP0-9-1使用许多channel来共享一个connection的方法,来实现轻量化连接。

应用使用多个进程或者线程执行程序,一般都开一个新的channel给每一个进程或者线程而不是共享一个channel。

一个channel的信息是完全和另外的channel是分开的,因此每一个channel 的方法都带了一个叫channel number的,这样客户端就可以知道是哪个channel的方法了。

虚拟主机(Virtual Hosts)

为了实现一个单一的broker去host多个隔离的环境(用户组,exchanges,queues等等),AMQP引入虚拟host的概念(vhosts).和许多流行的web服务提供的虚拟host的非常相似,AMQP提供完全的隔离环境以供AMQP实体生存。在与AMQP的connect连接时。AMQP客户端指定怎样的vhost他们想连接


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!