事件驱动的发布订阅模型

时间:2012-03-26 11:46:42

标签: design-patterns publish-subscribe zeromq data-distribution-service

我正在制定一个要求,即一个流程(比如生产者)需要向可变数量的流程(比如消费者)发送单向消息。

发布 - 订阅模型似乎对此有好处,因为消费者将订阅来自生产者的消息。我尝试使用ZeroMQ来实现这一目标。

但是,我遇到了一些问题:

  1. 消费者必须不断轮询消息。当有新消息时,我会通知消费者。

  2. 生成器队列有可能被填满。我希望生产者根据某些条件从队列中删除消息(比如删除超过5秒的消息,或删除已被读取5次的消息)。

  3. 由于消费者正在轮询并且消息未从队列中删除,因此消费者会看到重复的消息,直到有新消息进入。我希望每个新消息只通知消费者一次。

  4. 我知道我可能使用了错误的模型(发布 - 订阅可能不合适)。我曾考虑使用请求 - 回复,但这不起作用,因为生产者不想跟踪消费者的数量。

    有人可以建议一个好的选择吗?

4 个答案:

答案 0 :(得分:1)

我建议在制片人和消费者之间选择Broker的Push-Pull模型。

  1. 应通知经纪人任何新消息。
  2. 消费者会听经纪人通知(保持表跟踪成功/失败。重试期间将避免重复)
  3. 一旦#2完成,消费者就可以从Producer(来源)提取数据并将ack发送给经纪人以获得成功/失败
  4. 希望这有帮助

答案 1 :(得分:0)

您需要多个制片人吗?如果不是,你可以使用PUSH / PULL而不是PUB / SUB。

使用PUSH / PULL,您可以拥有任意数量的消费者(他们是模型的PULL方面)。写入PUSH端点的所有消息都是在所有连接的消费者中以循环方式分发的。这也确保了两个消费者不会收到相同的消息。

正如您所描述的那样,如果两个或多个消费者订阅了相同的“前缀”,那么将消费者作为SUB端点可以最终向多个消费者提供相同的消息(假设这在您的模型中会出现问题)

假设“prefix”是您传递给sock.setsockopt(ZMQ_SUBSCRIBE, "prefix", ...);

的字符串

答案 2 :(得分:0)

尝试使用JMS提供程序或AMQP提供程序。这些有一些你正在寻找的主题:

  1. 向订阅者推送通知。

  2. 消息的生存时间属性,如果消息未在TTL内消费,则允许删除消息或将消息放入死信队列。

  3. 一次性通知 - 取决于您的配置。

  4. 请注意,只有一次消息传递在网络故障的情况下确实存在边缘条件,这可能导致丢失消息或重复消息......您选择。

    就哪个提供者而言。 RabbitMQ是AMQP的热门产品。对于JMS,有许多专有产品或开源实现。

答案 3 :(得分:0)

DDS(数据分发服务)中间件支持您正在尝试实现的内容,并且更加轻松。

直接回答你的问题:

  1. DDS支持监听器机制,您的订阅者无需连续轮询。

  2. DDS具有良好的QoS设置,可防止发布者队列被填满。您可以使用历史QoS来说“仅保留队列中的最新10个样本”,或者您可以使用Lifespan QoS说“仅保留最近10秒内发布的样本”。

  3. 同样,您可以使用DDS侦听器机制,每个新样本只会收到一次通知。无需民意调查。

  4. 目前有两种开源实现方式。