(接上文《架构设计:系统间通信(19)——MQ:消息协议(上)》)3-3、AMQP协议 3-3-1、协议概览   AMQP协议中的元素包含:Message(消息体)、Producer(消息生产者)、Consumer(消息消费者)、Virtual Host(虚拟节点)、Exchange(交换机)、Queue(队列)等   由Producer(消息生产者)和Consumer(消息消费者)构成了AMQP的client 。他们是发送消息和接收消息的主体。AMQP服务端称为Broker,一个Broker中一定包含完整的Virtual Host(虚拟主机)、 Exchange(交换机)、Queue(队列)定义。   一个Broker能够创建多个Virtual Host(虚拟主机),我们将讨论的Exchange和Queue都是虚拟机中的工作元素(还有User元素)。   Connection是由Producer(消息生产者)和Consumer(消息消费者)创建的连接,连接到Broker物理节点上。可是有了Connection后client还不能和server通信,在Connection之上client会创建Channel。连接到Virtual Host或者Queue上。这样client才干向Exchange发送消息或者从Queue接受消息。一个Connection上同意存在多个Channel,仅仅有Channel中能够发送/接受消息 。   Exchange元素是AMQP协议中的交换机,Exchange能够绑定多个Queue也能够同一时候绑定其它Exchange 。消息通过Exchange时,会依照Exchange中设置的Routing(路由)规则,将消息发送到符合的Queue或者Exchange中 。 
 
   在Producer(消息生产者)client建立了Channel后,就建立了到Broker上Virtual Host的连接。   Exchange(交换机)能够处理消息的前提是:它至少已经和某个Queue或者另外的Exchange形成了绑定关系。并设置好了到这些Queue和Excahnge的Routing(路由规则) 。Excahnge中的Routing有三种模式。我们随后会讲到。在Exchange收到消息后。会依据设置的Routing(路由规则),将消息发送到符合要求的Queue或者Exchange中(路由规则还会和Message中的Routing Key属性配合使用)。   Queue收到消息后,可能会进行例如以下的处理:假设当前没有Consumer的Channel连接到这个Queue,那么Queue将会把这条消息进行存储直到有Channel被创建(AMQP协议的不同实现产品中,存储方式又不尽同样);假设已经有Channel连接到这个Queue,那么消息将会按顺序被发送给这个Channel。   Consumer收到消息后,就能够进行消息的处理了。Queue在收到这条ACK信息后,才会觉得这条消息处理成功,并将这条消息从Queue中移除 。假设在相应的Channel断开后,Queue都没有这条消息的ACK信息,这条消息将会又一次被发送给另外的Channel。当然,您还能够发送NACK信息,这样这条消息将会马上归队。并发送给另外的Channel 。 3-3-2、Message(消息体) 实际上AMQP协议要比Stomp协议复杂得多 。以下我们就依据ISO/IEC公布的AMQP Version 1.0标准文档。来讨论一下AMQP协议中的消息格式。有的文章还向读者传递了错误的信息。 比如说AMQP消息格式包含两部分:消息头和消息正文。  这是全然错误 的,尽管AMQP消息格式确实包含Header和Body部分。可是绝对不止这两个部分。(假设真是这样,ISO/IEC组织就不须要使用125页的文档篇幅来进行说明了)作为一种网络通讯协议,AMQP工作在七层/五层网络模型的应用层。是一个典型的应用层协议 ;另外。因为AMQP协议存在多种元素定义,且这些元素定义工作在不同的领域。比如Channel的定义是为了基于网络连接记录会话状态;Queue等元素帮助AMQP完毕路由规则,这些元素在Message消息记录中都须要有所体现。我们真正须要的内容存在PAYLOAD区域 。PAYLOAD区域(译文称为‘交付区’)的格式例如以下(能够在《OASIS Advanced Message Queueing Protocol   header:header部分记录了AMQP消息的在‘支持AMQP的中间件’中的交互状态。   delivery-annotations:在header部分仅仅能传递规范的、标准的、经过ISO/IEC组织定义的属性 。   message-annotations:这个数据区域,用于存储一些自己定义的辅助属性。和delivery-annotations区域的非标准信息不同。这里的自己定义属性主要用于消息的转换。   properties:从整个AMQP消息的properties属性開始,到AMQP消息的application-data部分结束,才是AMQP消息的正文内容(译文称为‘裸消息’)。Properties属性记录了AMQP消息正文的那些‘不可变’属性。在properties部分仅仅能传递规范的、标准的、经过ISO/IEC组织定义的属性 。   application-properties:‘应用数据’属性。在这部分数据中主要记录和应用有关的数据,AMQP的实现产品 (比如RabbitMQ)须要用这部分数据决定其处理逻辑 。比如:送入哪一个Exchange、消息的Routing值是什么、是否进行持久化等。   application-data:使用二进制格式描写叙述的AMQP消息的用户部分内容。既是我们发送出去的真实内容 。   footer:一般在这个数据区域存储辅助内容。比如消息的哈希值。HMAC。签名或者加密细节。 3-3-3、Exchange(交换机)路由规则 Exhange须要具备怎样的‘路由’规则,并没有在AMQP标准协议进行强行规定,眼下流行的AMQP转发规则都是AMQP实现产品自行开发的 (这也是为什么AMQP消息中和路由、过滤规则相关的属性是存放在application-properties区域的原因)。A、Direct路由 全然匹配 。就会将这条消息发送到这个Queue中。B、Fanout路由 复制多份 。分别发送到和自己绑定的各个Queue中。C、Topic路由 ‘#’表示0个或若干个关键词,‘ * ’表示一个关键词,注意是关键词不是字母 )。例如以下图所看到的:  “param.#”。能够匹配“param”、“param.test”、“param.value”、“param.test.child”等等AMQP消息的Routing Key;可是不能匹配诸如“param1.test”、“param2.test”、“param3.test”。   “param.*.* ”,能够匹配“param.test.test”、“param.test.value”、“param.test.child”等等AMQP消息的Routing Key;可是不能匹配诸如“param”、“param.test”、“parm.child”等等Routing Key。   “param.*.value”。能够匹配“param.value.value”、“param.test.value”等Routing Key;可是不能匹配诸如“param.value”、“param.value.child”等Routing Key。 假设Exchange交换机没有找到不论什么匹配Routing Key的Queue,那么这条AMQP消息会被丢弃。 4、不得不提的JMS规范 JMS不是消息队列,更不是某种消息队列协议。**JMS是Java消息服务接口,是一套规范的JAVA API 接口。这套规范接口由SUN提出,并在2002年公布JMS规范的Version 1.1版本号。**JMS和消息中间件厂商无关。既然是一套接口规范,就代表这它须要各个厂商进行实现 。好消息是,大部分消息中间件产品都支持JMS 接口规范。也就是说。您能够使用JMS API来连接Stomp协议的产品(比如ActiveMQ) 。就像您能够使用JDBC API来连接ORACLE或者MYSQL一样。  部分网络上的资料都介绍JMS是一个消息队列,这个说法是错误的,会误导读者。难道你能说JDBC是数据库?   当然。这些具体实现JMS规范的JAVA API都是由具体的中间件厂商提供的。用于描写叙述ActiveMQ消息中间件中实现的AMQP协议信息转换为JMS服务接口能够识别的数据信息 (请细致理解这句话黑体字部分的描写叙述)。http://activemq.apache.org/amqp.html5、后文介绍  
 
 
  
运维网声明 
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003运维网