消息排队模式

时间:2009-08-06 12:43:54

标签: design-patterns architecture

我们有两个架构。实质上,它们形成了生产者和消费者。第1部分(p1)将消息发布到处理消息的第2部分(第2页),此过程涉及将消息发送到远程节点,该消息必须在消息处理完消息后对其进行处理,此过程最多可能需要几秒钟。

p2在其队列中具有有限长度,并且在从远程节点接收到ack之前不会移除项目。由于这个p2可以返回对p1的QUEUE_FULL响应。当p1收到此响应时,它会保留一个队列,每当产生一条新消息时,它会将其添加到此队列的末尾,然后循环通过队列向p2发送消息,直到它再次获得QUEUE_FULL。这里的问题是,一旦p2的队列为空/有空间,它就无法通知p1产生消息。

对于p2中每个生产者实例,p1中都有一个相应的生产者,这对于下面的潜在解决方案很重要。

一个解决方案可能是p2可以更改为在队列中有空间时通知p1,但是这个解决方案需要相当大的网络开销(http),因为在任何时候都需要数千个p2队列需要通知他们相应的p1生产者。

另一个解决方案可能是p1可以更改以继续尝试将消息发送到p2。这个问题是p1中的生产者需要在尝试发送下一条消息之前有一个休眠x的线程,显然可能有一个处理这种睡眠/重试机制的单例,但是这里的逻辑,生产者和消费者增加到成千上万,变得相当复杂;

  • 添加,删除,生成器同步
  • 阅读队列,进行下一次阅读时间
  • 低生产者计数时紧密循环的注意事项
  • 高生产者计数时长时间等待的注意事项
  • .... etc

我接近建议一个MQ层,其中p1发布到,p2从中读取。然而,这引入了一个新问题,其中p2在远程节点消失时无法通知p1,但是这可以通过从p2到p1的http回调来处理 - 这里的开销水平是可接受的,因为远程节点的可能性是离开很低。

我是否缺少一种设计模式,可以消除对MQ的需求(另一项服务需要担心,监控等)?非常感谢。

其他一些细节:

  • 每个p1生产者实例大部分都是请求作用域
  • 每个p2使用者都是专用的运行线程

2 个答案:

答案 0 :(得分:3)

麦克,

似乎这个过程有很大的复杂性(有可能引入更多)只是为了避免使用MQ?根据我的经验,可能有很多理由不使用MQ,但是如果你有权使用它,那就放弃使用它! :)监视新MQ进程要比编写引入类似功能的代码容易得多。

理想情况下,强大的队列会阻止P1真正需要了解P2或其状态。

MQ还应该真正减少P2通知P1其远程节点发生故障的需要 - P1可以继续愉快地将消息排队到P2(取决于消息频率/大小/存储限制)。如果远程节点停机了很长时间,那么希望这是一个计划的事件,操作员可以关闭P1。 P2和P1之间的管理通道听起来很不错?

它还引入了额外的复杂性 - 你知道你的环境,但它可能导致诸如“为什么我不再收到消息?”之类的问题。 - 事实证明服务自动关闭另一项服务。做得好,这很棒,减轻了操作员的支持负担 - 做错了,只会增加更多的支持负担。没有人喜欢那个人。

您是否也可以在数据层排队,P2的存储可能不是一个问题?

拥抱队列(MQ,MSMQ,Sql Queue)!

ž

答案 1 :(得分:1)

回顾3种可能性

  • 如何为服务命令打开另一个MQ(而不是http调用);
  • 认为p2是多线程的,其中一个没有等待的线程从MQ中提取消息,并将它们放到另一个线程进行处理;
  • (!)使用MQ的事务版本 - 所以p2可以立即提取消息,p1可以尽可能快地放置它。但是如果处理失败,队列将被回滚。