代码之家  ›  专栏  ›  技术社区  ›  Mike

消息队列模式

  •  1
  • Mike  · 技术社区  · 16 年前

    我们有两个建筑。从本质上说,它们是生产者和消费者。件1(p1)将消息发布到件2(p2),件2(p2)处理消息,此过程涉及将消息发送到远程节点,远程节点必须在消息处理完成后对其进行确认,此过程最多需要几秒钟。

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

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

    一种解决方案是,当队列中有空间时,可以将p2更改为通知p1,但是此解决方案需要相当数量的网络开销(HTTP),因为在任何时候都是可行的,许多p2队列需要通知其相应的p1生产者。

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

    • 添加、删除、生产者同步
    • 读取队列,使下次读取时间
    • 生产商计数低时的紧密循环注意事项
    • 生产商计数高时长等待的注意事项
    • …等

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

    我是否缺少一个设计模式,它可以消除对MQ的需求(还有另一个需要担心的服务、监视等)?我很感激你的想法。

    其他一些细节:

    • 每个p1生产者实例的请求范围大部分是
    • 每个p2使用者都是一个专用的运行线程
    2 回复  |  直到 16 年前
        1
  •  3
  •   Zach Bonham    16 年前

    迈克,

    似乎流程有很大的复杂性(有引入更多的可能性),只是为了避免使用MQ?在我的经验中,可能有很多理由不使用MQ,代价很高,但是如果您有权使用它,那么您可以尽情地使用它!:)与编写代码引入类似功能相比,监视新的MQ进程要容易得多。

    理想情况下,健壮的队列会阻止p1真正需要了解p2或其状态。

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

    它还引入了额外的复杂性——您知道您的环境,但它可能导致诸如“为什么我不再收到消息?”-结果发现一个服务自动关闭另一个服务。做对了,这是可怕的,并减轻了运营商的支持负担-做错了,它只是增加了更多的支持负担。没人喜欢那个家伙。

    您还可以在数据层排队吗?在数据层中,p2的存储可能不太重要?

    接受队列(MQ、msmq、sql队列)!

    Z

        2
  •  1
  •   Dewfy    16 年前

    回顾3可能性

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