qpid接收消息编程

简介

Qpid 是 Apache 开发的一款面向对象的消息中间件,它是一个 AMQP 的实现,可以和其他符合 AMQP 协议的系统进行通信。Qpid 提供了 C++/Python/Java/C# 等主流编程语言的客户端库,安装使用非常方便。相对于其他的 AMQP 实现,Qpid 社区十分活跃,有望成为标准 AMQP 中间件产品。除了符合 AMQP 基本要求之外,Qpid 提供了很多额外的 HA 特性,非常适于集群环境下的消息通信

与 socket 的原始对应,企业级的应用软件往往有着各种各样从简单到复杂的通信需求,表现为不同的通信模型。常见的有:

  • 点对点:A 发消息给 B。
  • 广播:A 发给所有其他人的消息
  • 组播:A 发给多个但不是所有其他人的消息。
  • Requester/response:类似访问网页的通信方式,客户端发请求并等待,服务端回复该请求
  • Pub-sub:类似杂志发行,出版杂志的人并不知道谁在看这本杂志,订阅的人并不关心谁在发表这本杂志。出版的人只管将信息发布出去,订阅的人也只在需要的时候收到该信息。
  • Store-and-forward:存储转发模型类似信件投递,写信的人将消息写给某人,但在将信件发出的时候,收信的人并不一定在家等待,也并不知道有消息给他。但这个消息不会丢失,会放在收信者的信箱中。这种模型允许信息的异步交换。
  • 其他通信模型。。。

AMQP架构图

qpid

在 AMQP 模型中,消息的 producer 将 Message 发送给 Exchange,Exchange 负责交换 / 路由,将消息正确地转发给相应的 Queue。消息的 Consumer 从 Queue 中读取消息。这个过程是异步的,Producer 和 Consumer 没有直接联系甚至可以不知道彼此的存在。

Exchange 如何进行路由的呢? 这便依靠 Routing Key,每个消息都有一个 routing Key,而每个 Queue 都可以通过一个 Binding 将自己所感兴趣的 Routing Key 告诉 Exchange,这样 Exchange 便可以将消息正确地转发给相应的 Queue

安装服务端

yum install qpid-cpp-server
yum install qpid-tools
/etc/init.d/qpidd start


管理 qpid

默认情况下,Broker 启动之后,会自动创建一些 Exchange(交换器),对应 AMQP 标准定义的那几个标准的 exchange 类型。分别叫做

  • amp.topic
  • amp.direct
  • amp.fanout

应用程序可以建立 queue 并绑定到这些默认的 exchange 上进行信息收发。不过在真实的应用环境下,人们往往需要更多的 exchange,queue 以及 binding 来满足各种各样的需求。或者在一些复杂的网络中还需要配置 broker 的联邦,即一个相互路由的 broker 网络。 凡此种种都需要对 broker 进行各种配置,比如添加新的 exchange,queue,添加 broker 路由等等,这些便需要使用 Qpid 提供的各种管理工具。除配置管理之外,Qpid 的管理工具还提供了监控功能。常用的工具有三个:

  • Qpid-config
  • Qpid-route
  • Qpid-tool

Qpid-config 用来完成诸如添加 / 删除 Queue,添加 / 删除 Exchange 等关于 broker 内部的配置工作;Qpid-route 用来配置 broker Federation;Qpid-tool 用来对 Qpid Broker 进行实时监控

点对点通信(ptp通信类似写信)

其一,这种通信的异步的,人们把信发出去以后并不清楚何时能送到收信人的手中,在QPID中 sender将消息发送给Broker,并不要求Receiver在消息发送的时候也有一个和Broker的链接并准备接受该信息。sender只管将消息发送给Broker,就可以放手去做其他的事情了。

其二,信是唯一的,你写给朋友的信一定不希望其他人也收到吧,在qpid的ptp的通信中,一个receiver收到消息后,该消息就被消除,其他的receiver不能再收到

下面用例子来说明这种通信模型,首先需要建立一个Queue的节点。qpid目前有两种address一种叫Queue 一种叫Topic 我们这里使用queue这种节点,queue节点满足ptp通信的特征,储存转发和只接受一次

创建一个queue

qpid-config add queue hello-world

现在我们建立了一个叫做 hello-world 的 queue用 spout 发送消息给地址 hello-world:

[root@localhost api]# pwd
/tmp/qpid-python-0.20/examples/api
[root@localhost api]# ls
drain  hello  hello_xml  server  spout
[root@localhost api]# ./spout hello-world test
Message(properties={'spout-id': 'a083f3d4-f8c9-4201-ab87-8829557a902e:0'}, content='test')
[root@localhost api]# ./drain hello-world       
Message(properties={'x-amqp-0-10.routing-key': u'hello-world', u'spout-id': u'a083f3d4-f8c9-4201-ab87-8829557a902e:0'}, content='test')
[root@localhost api]# ./drain hello-world
[root@localhost api]# 

这就相当于将信发给了 hello-world。您已经看到,此时接收者 drain 还没有启动,但 Queue 的存储转发特性保证 drain 还是可以收到这条消息.当我们再次执行 drain,会发现不会再收到这条消息了。

Browse 模式 vs Consume 模式

一个有趣的的例子是如果我们修改一下 Address 的 Option,上面的通信模型就变成另外一种样子。之前我们看到,第二次执行 ./drain hello-world 将得不到任何信息,因为信息已经被第一次执行 ./drain 消费掉了。或者说这个 message 已经从 queue 里面移除了。这在 Qpid 中被称为消费模式 (Consume)。

有时候人们可能需要另外一种模式,叫做 Browse,即浏览。正如我们浏览网页上的新闻一样,一条新闻并不会因为第一个人阅读了它之后就被消费掉,从网页中消失了。而是一直在那里供人浏览。假如我们希望实现类似这种通信模式,不需要修改 spout 和 Drain 的代码,只需要稍微修改 Address 即可。Address 的选项 mode 可以用来设置 Browse 和 Consume 模式。如下例所示:

[root@localhost api]# qpid-config add queue my-queue
[root@localhost api]# ./spout my-queue one          
Message(properties={'spout-id': 'd034444e-b26a-416a-9fa0-6c830bd644f6:0'}, content='one')
[root@localhost api]# ./spout my-queue two
Message(properties={'spout-id': '8b4f4328-5ee1-45bb-aaf8-a4a8db290dad:0'}, content='two')
[root@localhost api]# ./spout my-queue three
Message(properties={'spout-id': 'b8893395-3a29-4b48-9395-5d8fb712a0b3:0'}, content='three')
[root@localhost api]# ./drain 'my-queue; {mode: browse}'
Message(properties={'x-amqp-0-10.routing-key': u'my-queue', u'spout-id': u'd034444e-b26a-416a-9fa0-6c830bd644f6:0'}, content='one')
Message(properties={'x-amqp-0-10.routing-key': u'my-queue', u'spout-id': u'8b4f4328-5ee1-45bb-aaf8-a4a8db290dad:0'}, content='two')
Message(properties={'x-amqp-0-10.routing-key': u'my-queue', u'spout-id': u'b8893395-3a29-4b48-9395-5d8fb712a0b3:0'}, content='three')
[root@localhost api]# ./drain 'my-queue; {mode: browse}'
Message(properties={'x-amqp-0-10.routing-key': u'my-queue', u'spout-id': u'd034444e-b26a-416a-9fa0-6c830bd644f6:0'}, content='one')
Message(properties={'x-amqp-0-10.routing-key': u'my-queue', u'spout-id': u'8b4f4328-5ee1-45bb-aaf8-a4a8db290dad:0'}, content='two')
Message(properties={'x-amqp-0-10.routing-key': u'my-queue', u'spout-id': u'b8893395-3a29-4b48-9395-5d8fb712a0b3:0'}, content='three')
[root@localhost api]# 
[root@localhost api]# 
[root@localhost api]# ./drain 'my-queue; {mode: browse}'
Message(properties={'x-amqp-0-10.routing-key': u'my-queue', u'spout-id': u'd034444e-b26a-416a-9fa0-6c830bd644f6:0'}, content='one')
Message(properties={'x-amqp-0-10.routing-key': u'my-queue', u'spout-id': u'8b4f4328-5ee1-45bb-aaf8-a4a8db290dad:0'}, content='two')
Message(properties={'x-amqp-0-10.routing-key': u'my-queue', u'spout-id': u'b8893395-3a29-4b48-9395-5d8fb712a0b3:0'}, content='three')

仅仅修改了Address的Option,我们就发现用spout和Drain可以实现另外一种通信模型了

sub-pub 通信的例子

Pub-sub 是另一种很有用的通信模型。恐怕它的名字就源于出版发行这种现实中的信息传递方式吧,publisher 就是出版商,subscriber 就是订阅者。

这种模型的特点在于:其一,消息可以根据订阅的信息而转发给不同的订阅者;其二,消息并不存储,broker 收到消息后立即将其转发给当时正在注册的订阅者,假如某个订阅者当时并没有链接到 broker,那么它就不能再收到该消息了。没有多少人愿意购买几天前的旧报纸吧?这是和 Queue 的一个区别。

创建一个 Topic 节点:

qpid-config add exchange topic hello-world

[root@localhost api]# 
[root@localhost api]# ./spout hello-world
Message(properties={'spout-id': '24b50d16-6190-42c4-ad29-932545061aea:0'})
[root@localhost api]# ./drain hello-world
Message(properties={'x-amqp-0-10.routing-key': u'hello-world', u'spout-id': u'24b50d16-6190-42c4-ad29-932545061aea:0'})

什么也没有收到。这说明消息没有被 broker 缓存

Pub-sub 的主要优点在于订阅消息的灵活性,broker 会根据消息的主题分发给不同的 subscriber。比如我们创建一个 news-service 的 exchange:

qpid-config add exchange topic news-service

打开两个 shell 窗口,一个运行 drain 并订阅 news-service/news,新闻;另一个订阅 news-service/ent 娱乐新闻:

[root@localhost api]# ./drain -t 120 news-service/#.news

[root@localhost api]#./drain -t 120 news-service/#.ent

回到qpid-config创建的界面执行下面的操作

[root@localhost api]# ./spout news-service/news
Message(properties={'qpid.subject': 'news', 'spout-id': '91242355-e586-4e47-b5d6-e33bf3624c5b:0'})
[root@localhost api]# ./spout news-service/ent
Message(properties={'qpid.subject': 'ent', 'spout-id': '3bde270a-3326-4408-a30a-386f1e0d943d:0'})
[root@localhost api]# ./spout news-service/usa.news
Message(properties={'qpid.subject': 'usa.news', 'spout-id': 'a2561005-c27f-4d72-8167-53250cb9a9e3:0'})
[root@localhost api]# ./spout news-service/usa.ent
Message(properties={'qpid.subject': 'usa.ent', 'spout-id': 'a2fe38b5-c803-4f29-a60b-a7bc006348f6:0'})
[root@localhost api]# ./spout news-service/usa.faux.news
Message(properties={'qpid.subject': 'usa.faux.news', 'spout-id': '65c6106c-8949-4da2-8b3d-63f22b25c521:0'})
[root@localhost api]# ./spout news-service/usa.faux.ent
Message(properties={'qpid.subject': 'usa.faux.ent', 'spout-id': '93a2b64a-33a8-491d-afe2-a9b0b8396eb1:0'})

会在打开的2个终端下有这样的显示

[root@localhost api]# ./drain -t 120 news-service/#.news
Message(subject=u'news', properties={u'qpid.subject': u'news', 'x-amqp-0-10.routing-key': u'news', u'spout-id': u'91242355-e586-4e47-b5d6-e33bf3624c5b:0'})
Message(subject=u'usa.news', properties={u'qpid.subject': u'usa.news', 'x-amqp-0-10.routing-key': u'usa.news', u'spout-id': u'a2561005-c27f-4d72-8167-53250cb9a9e3:0'})
Message(subject=u'usa.faux.news', properties={u'qpid.subject': u'usa.faux.news', 'x-amqp-0-10.routing-key': u'usa.faux.news', u'spout-id': u'65c6106c-8949-4da2-8b3d-63f22b25c521:0'})

[root@localhost api]# ./drain -t 120 news-service/#.ent
Message(subject=u'ent', properties={u'qpid.subject': u'ent', 'x-amqp-0-10.routing-key': u'ent', u'spout-id': u'3bde270a-3326-4408-a30a-386f1e0d943d:0'})
Message(subject=u'usa.ent', properties={u'qpid.subject': u'usa.ent', 'x-amqp-0-10.routing-key': u'usa.ent', u'spout-id': u'a2fe38b5-c803-4f29-a60b-a7bc006348f6:0'})
Message(subject=u'usa.faux.ent', properties={u'qpid.subject': u'usa.faux.ent', 'x-amqp-0-10.routing-key': u'usa.faux.ent', u'spout-id': u'93a2b64a-33a8-491d-afe2-a9b0b8396eb1:0'})

编写 Request/Response 模型的应用

在很多 P2P 和 Pub-Sub 应用中,Sender 和 Reciever 可以见面也不相识。他们多数情况下根本不关心对方是否存在。然而在现实中还有一种典型的通信模型:Request/Response。这种模型由 client 和 server 两部分组成,即人们常说的 C/S 模型。

Server 必须知道是谁发送了请求,以便回复给正确的 Requester。这是通过解析 Requester 发过来的消息中的 ReplyTo 字段得到的。

Broker Federation

最简单的情况下,一个系统中有一个 broker 和众多的 producer 以及 consumer,这很简单。不过当 client 的数目增加,消息的数目增加,或者网络的复杂性增加之后,一个中心的 broker 可能会有很多问题:

  • 比如负载过重,一个 broker 已经无法支撑众多的 client 和大量的消息
  • 比如通信组件所在的网络在地理上分布很广,而人们希望本地消息可以被本地的 consumer 接受,以便更快速地有所反馈
  • 等等

这些问题都可以采用 Federation 来解决。

Federation 就是一个 broker 的”云”,消息在 broker 云内部路由和分发负载,从而提高了吞吐率,也能够灵活配置路由达到消息分区的目的。 在本文中,我打算构建如下这样一个 Broker Federation: 在这个集群中,一共有 16 个节点。每个节点都将发送以下两类消息:

  • 关于体育 Sport 的消息:这类消息的数量很多,订阅者 (Consumer) 也很多
  • 关于文学欣赏的消息:这类消息的数量非常少,订阅者极少

我们可以采用单个 Broker 来处理转发所有的消息:

qpid

这么做的缺点在于 Node1 上的 Qpidd 将非常繁忙,如果消息继续增加,将出现丢包甚至停止服务的情况。这种情况下,我们可以采用 Federation 来均衡负载。

均衡负载的第一件事情是要详细分析这个消息系统,看看如何将消息处理均衡负载,划分出小的通信系统,将消息控制在小系统的合理范围内。

经过一些分析,人们会发现一些有趣的现象,比如消息本身的性质有很大不同:关于体育的消息非常多,而且每个 Node 上都有该消息的发布和接收者;而关于文学的则非常少,且只有少数节点上有对文学感兴趣的读者。让我们假设只有 Node2 上有对文学感兴趣的读者,也只有 Node2 上有对文学感兴趣的发送消息者。

针对这样一个系统,我们可以设计一个 Broker Federation 来均衡消息负载。

假设一个 Qpid Broker 能处理 2 个节点上的所有 sport 消息,那么我们可以让每两个 Node 共享一个处理 sport 消息的 broker。对于文学类的消息,则可以只在对文学感兴趣的 Node2 上启动 broker。这样就将负载均衡到多个不同的 Broker 上了。 但这样一个 Broker 的分布结构对 16 个节点上的 client 来说是不容易管理的,因为这意味这每个应用程序都必须知道相应的 broker 在哪个节点上。

一个通常的解决方法是在每个节点上设置一个 local node,client 只需要将消息发给 local node。而无需知道诸如文学 broker 在节点 2 上这样的条件。

Local node 通过 Federation 配置,将消息路由到正确的 broker。假如某一天网络拓扑需要改变,各个 client 程序无需修改。只需要重新配置路由即可。

这样的一个 Federation 如下图所示:

qpid

底层灰白色的小方框代表对 Sport 感兴趣的应用程序,他们分布在所有的节点上。他们和同节点的 Node Broker 进行信息收发。Node broker 会把关于 Sport 的消息路由到相应的 Sport Broker 上。在这个 Federation 中,每两个节点共用一个 Sport broker,换句话说,一个 Sport broker 需要处理来自两个 Node 上的 Sports 消息,这比处理 16 个 Node 上所有的消息来说负载轻了很多。黑色的小方块代表少数几个对文学感兴趣的应用程序,他们目前都分布在 Node2 上。

采用这样的 Federation,可以实现各种各样的功能和网络拓扑,最终所有的 Broker 组成了一个 Broker 云为各种各样的应用提供消息转发服务。

设置 federation 的命令叫 Qpid-route。

Qpid 支持两类路由:Queue routes 和 Exchange Routes。

Queue route:目的地必须是 Exchange,源是一个 Queue。此类路由将源地址 Queue 收到的所有消息都转发到目的 Exchange 去 Exchange Route:目的地依然必须是一个 Exchange,源也是一个 Exchange。此类路由允许将源 Exchange 上收到的,拥有指定 RouteKey 的消息转发到目的 Exchange 上去。

Qpid 路由是单向的,但是可以配置为”pull route”或者”push route”。如果是”pull route”,那么实际上是目的地 Broker 需要不断地主动接收 (receive) 源 Broker 的消息;反之就是源 Broker 主动将消息发送 (Send) 到目的 Broker 去。这取决于谁更加空闲,因为主动发送 / 接收的一方需要更多的资源。在上面的例子中,每个 Node 上的 Broker 相对于处理 Sports 的 Broker 负载更低,因此应该选择”push route”,由 Node broker 主动将消息转发给 Sports broker。

为了配置上图所示的 Federation,我们需要运行下面这些假想的命令:

qpid-route – s route add node1:10001 node1:10002 amq.topic sports.# 
qpid-route – s route add node2:10001 node1:10002 amq.topic sports.# 
qpid-route – s route add node3:10001 node3:10002 amq.topic sports.# 
......
qpid-route – s route add node16:10001 node15:10002 amq.topic sports.# 

配置关于文学的路由:

qpid-route – s route add node2:10001 node2:10003 amq.topic novel.#

以上配置假设 Node broker 运行在端口 10001 上;Sports broker 运行在端口 10002 上;Novel Broker 运行在端口 10003 上。我们采用 Exchange 路由,采用源地址为 node broker 的”push route”方式。

持久化消息

消息从一个 client 发送出来,交给 Broker,然后 Broker 将其转发给相应的接收者。在这个过程中,假如 broker 进程被中断,那么保存在 Queue 中的消息就会丢失。为了避免这类信息丢失,人们可以选择将消息持久化。Broker 将收到的消息暂存在磁盘等可以永久保存信息的地方备用,这样,即使 Broker 因为某种意外而中断,当其再次重新启动之后,还是可以将保持在永久存储介质中的消息读出来并继续进行转发。

在我写这篇文章的时候,Qpid 正式版本为 0.8 版本。在这个版本的源代码中,还没有实现 persistent 存储的 plugin。必须从第三方下载相应的 plug-in。

在 Linux 下,可以使用 QpidComponents 项目提供的 plugin。这个插件,采用 Berkeley DB 作为后台数据库存储 Qpid 需要持久化的数据,在 License 方面和 Qpid 有所冲突,因此不能随 Qpid 一同发布。根据 Qpid 邮件列表中的讨论,已经有开发人员采用 MS SQL 写了插件,并将随 Qpid 源代码一同发布,让我们拭目以待吧。

但现在,我们必须先用 SVN 将代码 checkout 出来,然后编译,编译的前提条件是系统已经安装了以下几个软件:

 - libaio-devel libs 
 - qpid broker headers and libraries (see below) 
 - all prerequisites for qpid (see qpid's cpp/INSTALL file) 
 - berkeley db4  (tested with version 4.3.29) 
 - python (to run system tests) 

安装

svn checkout http://anonsvn.jboss.org/repos/rhmessaging/store/ -r 4411 
 ./bootstrap 
 ./configure --with-qpid-checkout=qpid-dir 
 make 

首先启动 Broker:

qpidd --load-module=/$path/msgstore.so --data-dir=/$pathd/store-files ... 

创建一个 durable 的 Queue。就叫做 abc 吧。

./qpid-config add queue abc --durable 

除了 Queue 需要 durable 之外,我们还必须保证发送的消息有 durable 属性。为此我们必须对 spout 例子程序进行一点儿修改,假如下面这一行代码,将消息设置为 durable 消息。

message.setDurable(true); 

用 spout 发送数据。

./spout abc 

现在将 qpidd 进程杀掉。然后重新启动 broker,最后再运行 drain 接受数据。

./drain abc 
 Message(properties={spout-id:cece972c-f194-4597-b0f4-7131f7bcb768:0,x-amqp-0-10.routing-key:abc}, content='') 

可以看到,数据在 Qpidd 重启之后没有丢失。

持久化消息,提供了某种程度上的可靠性,但是在真正的 HA 环境下,这种简单的保护还无法满足要求。因为通信恢复的前提条件是被中断的 Broker 又重新启动。在生产环境中,有 HA 要求的系统往往对 downtime 也有很高的要求,对于用户来说 Broker 的中断应该是透明的。这便需要 Qpid 的 HA 特性,Broker 集群。

采用集群 broker 提供高可用性

作为消息中间件,Qpid broker 能高效地完成信息的转发任务,并提供极高的吞吐量,它采用多种设计来提高信息系统的可用性。然而,假如运行 Broker 的物理节点发生故障,比如掉电或者网络中断等事故,那么自然在该节点上运行的 broker 也无法继续提供服务了。

对于追求 HA 的用户,可以考虑采用 Qpid broker 集群来避免这类故障导致的服务中断。在一个 Qpid broker 集群中,所有的 broker 都互相备份,进行 fail over 的必要准备工作。每个 broker 的内部对象都同步到其他集群中的 Broker,保持一致,这样在单一 Broker 无法工作的情况下,client 可以切换到其他 Broker,而避免信息的丢失和服务中断。 Qpid 采用 Corosync 作为通信层,利用 Corosync,集群中的每一个 broker 都采用组播通信将自己的状态同步给集群中的其他 broker。

此外,Qpid 和 RHCS 紧密集成,它可以采用 CMAN 防止集群中的“脑裂”问题,也可以使用 rgmanager 自动重启 failed 的 Qpid。当然,不一定非要使用 RHCS 来搭建您的集群,也可以使用其他的 CRM 集群管理软件来管理 Qpidd。Qpidd 本身只是使用了 Corosync 来完成同步通信,可以使用 CMAN 来防止“脑裂”问题。 工作模式如下:

Qpid 和 Corosync 的工作模式

qpid

Qpidd A 和 QpiddB 通过 Corsync 同步,假如 Qpidd B 新建了一个 Queue,那么这个状态改变将通过 Corosync 发送给集群中的其他 broker,上图中的 Qpidd A 收到 Qpidd B 的状态改变消息,于是也添加一个新的 queue,保证和 Qpidd B 同步。这样,假如 Qpidd B 停止工作了,Qpidd A 可以继续提供同样的服务。

Qpid 还通过 CMAN 来防止集群中的”split brain”问题,CMAN 提供了 quorum 算法,Qpidd 利用 CMAN 的接口,知道自己是否能够达到法定人数,是否能够加入集群工作。

在一个 Qpid 集群中,每个 Qpid broker 都有自己独立的存储空间,并不像某些集群方案那样共享存储。Queue,Exchange 等都保存在每个 Broker 自己的存储空间中,通过 Corosync 同步彼此的状态。因为不需要共享存储,因此在 broker 集群中并不需要 Fence Device。

Qpid 集群是一个 Active/Active 模式的集群。客户端可以使用任意一个 broker。如下图所示: Client 连接一个 Broker

qpid

当 client 连接到一个集群中的 broker 时,该 broker 返回给 Client 相应的 Broker URL 列表。在上图中,Client 将得到 [QpiddA,QpiddB] 这样一个列表。当 QpiddA 的连接断开时,客户端可以自动重新连接到 QpiddB 继续服务: Client failover

qpid

在集群中启动一个 broker:

启动集群中的 broker 只需要多设置几个命令行参数即可: --cluster-name:指定 cluster 的名字,即 Corosync 中的 CPG 的名字。每个参加集群的 broker 都必须用同一个 cluster-name,以便假如同一个集群。

--cluster-size:指定 cluster 中节点的数目,假如指定了这个数字,在 broker 数目未达到的情况下,所有的 broker 都不能开始工作。

--cluster-url:返回给 client 端的 broker 列表。缺省情况下,broker 将返回集群中所有 broker 的列表,但假如指定了本参数,那么将只返回这里指定的 broker 列表。

--cluster-cman:指定使用 CMAN 来防止"split-brain"

让 client 支持 failover

让 client 支持 failover 十分容易,只需要在初始化的时候加入以下几行代码即可,Qpid 的客户端代码库,能够自动从 server 返回的消息中知道其他 active broker 的 url,当正在连接的 broker 失效时,Qpid 客户端能够自动连接其他的 broker。

1
2
3
4
5
6
7
#include <qpid/messaging/FailoverUpdates.h> 
 ... 
 Connection connection("localhost:5672"); 
 connection.setOption("reconnect", true); 
 try { 
 connection.open(); 
 std::auto_ptr<FailoverUpdates> updates(new FailoverUpdates(connection)); 

修改 Client 端代码,设置连接属性 reconnect,并构造一个 FailoverUpdates 对象。这样当一个 node 失效后,client 能够自动连接到其他的 broker 上。从而保证服务的连续。

 2013-12-18  tags in qpid 编程

posted @ 2013-12-25 17:39  孤火  阅读(3230)  评论(0编辑  收藏  举报