随笔)基于路由的消息传输系统(2)

消息系统的路由体系
    消息系统由多个路由节点组成。一个消息从发送端经过一个或多个节点最总传输到接收端。每经过一个路由节点,通常够经历相同的操作:把消息写入指定的消息队列、把消息传输至下一个节点或接收者。消息的路由体系就是用来决定一个消息应该写入哪个队列、它的下一个传输节点是哪一个的规则和方法。
    简单路由。最简单的基于MQ的消息系统是发送端+一个MQ服务器+接收端。这种消息系统显然不需要在路由体系上做什么研究。
    为了方便起见,把消息服务器节点缩写成MQ,这里的MQ不是特定的MQ产品。
    网络连接和传输队列。消息服务器之间的消息传递是最基本得方式就是把指定传输队列里的消息通过指定的网络连接发送至下一路由节点。每个传输队列都关联一个消息服务器节点,即一个传输队列的所有消息都是将发送至一个指定的服务器节点的。例如MQ1上的传输队列to_mq2@mq1上所有的消息都将被传输模块(或称传输代理程序)发送至MQ2。网络连接和相关的传输队列是整个路由体系的基础。所谓的消息路由体系就是一个选择传输队列的过程。消息服务器通过路由体系为每个消息选择/确定写入的传输队列,那么消息的传输路由也就确定了。

静态路由
    消息的路由规则是静态的,预先配置好的。消息系统配置、构建完之后,消息从发送端到最终目的地的路由是确定的。举个例子: 消息系统网络结构是 发送端->MQ1->MQ2->接收端。
    发送的消息指定消息目的地是位于MQ2上的queue2@mq2.当MQ1收到该消息后,把它写入专门连接MQ2的传输队列to_mq2@mq1(该队列的消息全部发送至MQ2)。随后MQ的传输模块(或称传输代理程序)把to_mq2@mq1里的消息传输至MQ2,MQ2收到消息后写入最终目的地queue2@mq2。
   由于消息的目的地不在MQ1,所以MQ1的路由体系必需以某种方式确定如果传输该消息。在上面的例子当中,MQ1的路由系统存在如下的配置:1、配置到MQ2的网络连接。2、传输队列to_mq2@mq1里的所有消息都发送至MQ2。3、目的地是MQ2的消息将被写入队列to_mq2@mq1.
  再复杂一点的例子:发送端->MQ1->MQ2-MQ3->接收者。在MQ1上需要配置这样的规则:所有目的地在MQ2和MQ3上的消息都将发送至MQ2;在MQ2上配置的规则:所有目的地在MQ3上的消息都将发送至MQ3.更多的路由节点使用相同的逻辑。
    自动路由/智能路由。每个MQ节点只预先配置直接连接的其他MQ。运行时使用特定的算法在连通的MQ网络中动态传播连通状态。服务器根据动态的连接信息确定每个消息选择下一个路由节点。这种方式相对静态路由的好处是简化配置、在某个路由断开时可自动选择其他路由(如果存在)。但是,这种方式只适合简单的直线型的网络拓扑。对于复杂的网络拓扑结构,很难实现一个好的算法能够得到一个理想的、预期的路由,而且存在着路由的不确定性。就本人的实践经验来说,不建议在路由体系中使用这样的方式。如果使用静态路由规则来实现相同的功能,需要用静态配置的方式指定所有可能的目的地的的下一个路由节点及其关联的传输队列,引入备份路由的机制及其策略。
 
    基于内容的路由。如果只有静态路由,路由体系就没什么
可研究的了。虽然各个MQ产品的实现方式不尽相同,但毕竟MQ产品已经发展了十多年,静态路由体系已经很成熟、完整了。很容易理解,这种方式是根据消息的内容确定消息的路由。现有的MQ产品中的Topic和集群路由都使用到了这种机制,但都不是在架构层次上设计实现的。主流的MQ产品对Topic、集群等特性的路由实现机制都是分散的、并且存在多个网络通讯协议,这也许是多年的发展/进化过程中的历史遗留问题。我心目中的理想的系统架构就是要设计一个清晰的、统一的了路由体系并以此作为基础。
    从架构层次上来说,基于内容的路由只是一个抽象的层次。并且它在最底层,所有的消息路由都是从它开始,通过以它为基础的路由体系最终确定该消息的下一个路由节点及其传输队列,或本地队列。比如静态路由,相关的消息内容是消息的目的地服务器及队列,静态路由根据此内容来确定下一个路由节点及其传输队列或本地队列。
    Topic路由。Topic(主题订阅发布)机制是在JMS规范里定义的。最初的IBM MQ产品并未实现此功能,其他的MQ产品基本上也都是在队列基础上单独实现的。在其路由机制上都没有一个统一的架构模型。
    Topic机制包含订阅和发布两个部分。在分布网络的订阅需要订阅信息的传播机制。
    主题的订阅信息及其传播是需要认真考虑的。在分布式网络环境中你不能把主题消息先广播到所有网络节点,然后再确定该节点是否存在本地订阅者。这样会存在大量的无效传输,浪费网络资源。相对发布主题消息来说,订阅信息要少得多,因此需要在消息系统中传播订阅者信息,特别是在分层网络结构下,订阅者信息可以被进一步合并,从而减少网络资源的使用。关于消息服务器之间的信息传播、分层网络以及Topic的订阅信息传播实现机制的内容以后单独讨论。

    主题消息的发布的路由机制是一个典型的基于内容的消息路由机制。路由体系根据主题内容(通常是一个主题字符串),并结合预先收集的订阅者信息,来确定该主题消息有(或没有)哪些感兴趣的订阅者及这些订阅者的目的地服务器和接收队列。然后再通过静态路由体系确定该消息将被分发至哪些本地接收队列和下一个路由节点。在分发过程中还会考虑同一路由节点只会复制一份消息。
    广播、多播、组播一个消息的目的地可以指定多个接收者、可以包含通配符或类似的机制、可以把系统定义的接收分组信息作为接收者。路由体系解析这种复合的目的地,并确定多个(或没有)目的地队列(本地队列或关联其他节点的传输队列)。接收分组信息的实现机制类似Topic。
    动态路由这里的动态路由指的是一个用户或服务提供者动态地关联到一个具体的系统节点及接收队列的功能。类似动态域名的实现机制,一个用户或服务提供者可以在某个系统节点上建立连接、并且绑定一个接收队列后(通常是临时队列),通知消息系统(广播或通过一个确定位置的动态路由服务器)该用户的用户信息或服务提供者的服务信息,以及相关联的系统节点和接收队列。
    服务访问的请求/应答请求消息需要指定发送者用于接收应答消息的目的地,通常是本地服务器指定接收队列。请求消息还需要指定要访问的服务名称。路由体系根据预先定义或收集的服务提供者信息(可能是动态路由机制)来为这个消息确定服务提供者的接收目的地服务器和队列。
    负载均衡集群路由现有MQ产品的负载均衡集群通常是定义集群共享队列的方式,当然,根据上面的讨论,也可以扩展成服务访问的负载集群模式。路由体系所要做的是根据当前的服务提供者/共享队列信息以及消息的来源及其分组信息等,为该消息选择一个可用的集群节点及其接收队列。当然,集群路由只是集群功能的一部分,相对来说,集群管理(尤其是运行时的集群动态管理)要更为复杂。如果有时间并且有思路的话,以后会专门讨论。

猜你喜欢

转载自taolei0628.iteye.com/blog/1150072