简体   繁体   English

消息排队模式

[英]message queuing patterns

We have two pieces of architecture. 我们有两个架构。 In essence they form a producer and a consumer. 实质上,它们形成了生产者和消费者。 Piece 1 (p1) publishes messages to Piece 2 (p2) which processes the message, this process involves sending the message to a remote node, which must ack the message once it has processed it, this process can take a few seconds at best. 第1部分(p1)将消息发布到处理消息的第2部分(第2页),此过程涉及将消息发送到远程节点,该消息必须在消息处理完消息后对其进行处理,此过程最多可能需要几秒钟。

p2 has a finite length in its queue and items are not removed until it receives the ack from the remote node. p2在其队列中具有有限长度,并且在从远程节点接收到ack之前不会移除项目。 Due to this p2 can return a QUEUE_FULL response to p1. 由于这个p2可以返回对p1的QUEUE_FULL响应。 When p1 receives this response it keeps a queue, whenever a new message is produced it adds it to the end of this queue and then cycles through the queue sending messages to p2 until it once again gets a QUEUE_FULL. 当p1收到此响应时,它会保留一个队列,每当产生一条新消息时,它会将其添加到此队列的末尾,然后循环通过队列向p2发送消息,直到它再次获得QUEUE_FULL。 The problem here is that once p2's queue is empty/has space it isn't able to notify p1 to produce the messages. 这里的问题是,一旦p2的队列为空/有空间,它就无法通知p1产生消息。

For each instance of producer in p2 there is a corresponding producer in p1, this is important when it comes to the potential solutions below. 对于p2中生产者的每个实例,p1中都有一个相应的生产者,这对于下面的潜在解决方案很重要。

One solution could be that p2 could be changed to notify p1 when there is space in its queue, however this solution requires a fair amount of network overhead (http) as it is feasible at any one time many thousands of p2 queues need to notify their corresponding p1 producers. 一个解决方案可能是p2可以更改为在其队列中有空间时通知p1,但是此解决方案需要相当大的网络开销(http),因为在任何时候都有数千个p2队列需要通知他们相应的p1生产者。

The other solution could be that p1 could be changed to keep attempting to send the message to p2. 另一个解决方案可能是p1可以更改为继续尝试将消息发送到p2。 The problem with this is that a producer in p1 needs to have a thread that sleeps x before trying to send the next message, clearly there could be a singleton that handles this sleep/retry mechanism however the logic here, as producers and consumers increases to many thousands, gets rather complex; 这个问题是p1中的生产者需要在尝试发送下一条消息之前有一个休眠x的线程,显然可能有一个处理这种睡眠/重试机制的单例,但是这里的逻辑,生产者和消费者增加到成千上万,变得相当复杂;

  • synchronization on adding, removing, producers 添加,删除,生成器同步
  • reading queues, making next read times 阅读队列,进行下一次阅读时间
  • considerations for tight looping when low producer count 低生产者计数时紧密循环的考虑因素
  • considerations for long waits when high producer count 高生产者数量时长时间等待的考虑因素
  • .... etc ......等

I'm close to suggesting a MQ tier where p1 publishes to and p2 reads from. 我接近建议一个MQ层,其中p1发布到,p2读取。 However this introduces a new issue where p2 is not able to notify p1 when the remote node goes away, however this could be handled by a http call back from p2 to p1 - the level of overhead here is acceptable as the chance the remote node goes away is low. 然而,这引入了一个新问题,其中p2在远程节点消失时无法通知p1,但是这可以通过从p2到p1的http回调来处理 - 这里的开销水平是可接受的,因为远程节点的可能性是离开很低。

Am I missing a design pattern which would remove the need for an MQ (yet another service to worry about, monitor, etc)? 我错过了一个设计模式,它将不再需要MQ(另一个服务需要担心,监控等)? Thoughts much appreciated. 非常感谢。

Some other details: 其他一些细节:

  • each p1 producer instance is request scoped for the most part 每个p1生成器实例大部分都是请求作用域
  • each p2 consumer is a dedicated running thread 每个p2使用者都是一个专用的运行线程

Mike, 麦克风,

It seems like the process has a significant amount of complexity (with the possibility of introducing more) just to avoid using MQ? 看起来这个过程有很大的复杂性(有可能引入更多)只是为了避免使用MQ? There may be plenty of reasons NOT to use MQ, cost in my experience, but if you have access to it, use it with wild abandon! 根据我的经验,可能有很多理由不使用MQ,但是如果你有权使用它,那就放弃使用它! :) Its far easier to monitor the new MQ process than it is to write the code to introduce like capabilities. :)它比监视代码以引入类似功能更容易监视新的MQ进程。

Ideally, a robust queue would prevent P1 ever really needing to know about P2, or its status. 理想情况下,强大的队列会阻止P1真正需要了解P2或其状态。

MQ should also really mitigate the need for P2 to notify P1 that its remote node went down - P1 can continue to happily queue up messages to P2 (depending on message frequency/size/storage limits). MQ还应该真正减少P2通知P1其远程节点发生故障的需要 - P1可以继续愉快地将消息排队到P2(取决于消息频率/大小/存储限制)。 If the remote node is down for a significant amount of time, then hopefully it was a planned event and operators can shutdown P1. 如果远程节点停机了很长时间,那么希望这是一个计划的事件,操作员可以关闭P1。 The administrative channel between P2 and P1 sounds like a nice to have? P2和P1之间的管理通道听起来很不错?

It also introduces additional complexity - you know your environment, but it can lead to questions like "why am I not getting messages anymore?" 它还引入了额外的复杂性 - 你知道你的环境,但它可能导致诸如“为什么我不再收到消息?”之类的问题。 - turns out that a service autonomously shutdown another service. - 事实证明服务自动关闭另一项服务。 Done right, this is awesome and relieves a support burden for the operators - done wrong, it just adds more support burden. 做得好,这很棒,减轻了操作员的支持负担 - 做错了,只会增加更多的支持负担。 Nobody likes that guy. 没有人喜欢那个人。

Could you also queue at the data tier, where storage for P2 might not be as much of an issue? 您是否也可以在数据层排队,P2的存储可能不是一个问题?

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

Z ž

Review 3 possibility 回顾3种可能性

  • What about open yet another MQ for service commands (instead of http invocations); 那么为服务命令打开另一个MQ(而不是http调用);
  • consider p2 be multithread, where one thread without waits extracts messages from MQ, and places them to another thread for processing; 认为p2是多线程的,其中一个没有等待的线程从MQ中提取消息,并将它们放到另一个线程进行处理;
  • (!) use transactional version of MQ - so p2 could extract messages immediatly and p1 can place it as fast as it can. (!)使用MQ的事务版本 - 所以p2可以立即提取消息,p1可以尽可能快地放置它。 But if processing fails, queue will be rolled back. 但是如果处理失败,队列将被回滚。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM