没有中介的ZeroMQ发布-订阅+动态发现

12
我正在测试ZeroMQ作为中型系统的Pub-Sub(服务总线)基础设施。我们大约有50个节点,所有这些节点都应该是发布者和订阅者。网络有点像星形拓扑结构,但边缘之间会“通信”。我们需要动态发现(无需硬编码参与者的网络地址),但也不需要单点故障(SPOF)。
我已经阅读了http://zeromq.org/whitepapers:0mq-3-0-pubsub,根据我的理解,建议的ZeroMQ实现动态发现的方法涉及代理节点(XPUB/XSUB),该节点转发订阅和发布。 我考虑在我们的系统中使用这样的代理作为中心协调器,然而,我对这种架构有以下担忧: (A) 代理节点是SPOF-当它失败时,整个系统将不起作用 (B) 所有流量,包括数据,都通过代理节点传递,这意味着延迟和性能问题。 假设我正确理解了pub-sub白皮书,有没有相对简单的方法来实现ZeroMQ的pub-sub + 动态发现 + 无SPOF?

附加说明:我已排除多播(PGM)解决方案,因为大多数消息只有一个/少数感兴趣的方,我们不希望过度拥挤网络。

1个回答

9

一个发布者多个订阅者不需要中介,因为订阅者可以直接与发布者通信。但同时存在许多发布者和订阅者不太容易;除非有中间件,否则维护将是一场噩梦,因为新的订阅者需要配置所有现有的发布者。

您可以在不同的机器上部署多个XSUB/XPUB代理,然后在发布者和代理之间部署一个负载均衡器(如F5)。这样可以实现上游的负载均衡和容错。

代理代码很简单:

Socket frontend = context.socket(ZMQ.XSUB);
frontend.bind("tcp://proxy1:5444");
Socket backend = context.socket(ZMQ.XPUB);
backend.bind("tcp://proxy1:5555");
frontend.subscribe("".getBytes());
ZMQ.proxy (frontend, backend, null);

如果代理节点出现故障,只需重新启动它;重新连接/订阅应由zmq自动处理。
对于下游订阅者,将每个订阅者直接连接到所有可用的代理。
subscriber = ctx.createSocket(ZMQ.SUB)
subscriber.connect( "tcp://proxy1:5555")
subscriber.connect( "tcp://proxy2:5555")
subscriber.connect( "tcp://proxy3:5555")

与代理相比,出版者的进出更加频繁。因此,将订阅者直接连接到代理会导致更少的配置维护,因为代理数量在很大程度上是静态的。

如果代理节点失败,上游 LTMs 会根据需要将流量路由到剩余的代理节点;由于订阅者从所有可用的代理节点中获取数据,因此他们不会受到影响。

可以使用同步来解决慢订阅者问题,请参阅此处。查看此处了解订阅转发和最小化网络流量。

enter image description here


实际上,我对提出的解决方案中的某些内容并不理解:当任何订阅者订阅时,轮询DNS将重定向订阅消息到某个LTM,该LTM将将其重定向到某个(单个?)代理,该代理将保留订阅。如果此代理机器崩溃,则订阅将丢失,是吗? - dux2
谢谢。在这种解决方案中,您如何避免在每个代理中静态配置发布者列表?您如何处理后加入的发布者?我可以想到一种方法是发布者在启动时向每个代理“宣布”其存在,然后代理将所有订阅发送给新发布者。代理如何从崩溃中恢复?它必须从所有订阅者那里重新订阅或使订阅持久化。这都是可能的,但需要编写大量代码,几乎就像从头开始开发自己的发布-订阅系统一样。 - dux2
再次更新,希望能有所帮助。 - raffian
在最后一次修订中,代理如何连接到实际发布者或反之亦然?此外,您是否建议使用多播(DDS风格)实现动态发现,而不是使用代理?那样会更简单吗? - dux2
代理服务器使用bind,发布者和订阅者使用connect - raffian
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接