简体   繁体   English

Pub-Sub 模式和消息代理,如何确保所有订阅者完成对事件的处理

[英]Pub-Sub pattern and message broker, how to make sure all subscribers finished working on event

First of all, I am aware that there are good (and lightweight) message brokers available like NATS.首先,我知道有像 NATS 这样的优秀(轻量级)消息代理。 If this was a job, I'd certainly go with proven solutions, this is more about curiosity and the will to understand.如果这是一份工作,我肯定会使用经过验证的解决方案 go,这更多是出于好奇心和理解的意愿。

Let's say I want to build a system like a CRM and I want to base it on microservices so it is easily extensible and can be adapted to workloads.假设我想构建一个像 CRM 这样的系统,并且我想将它基于微服务,以便它易于扩展并且可以适应工作负载。 Since microservices should be decoupled.因为微服务应该是解耦的。 In comes pub-sub.进来了 pub-sub。 In order for pub-sub to work as intended (decoupling of publisher and subscriber) I need a messaging system.为了使发布订阅按预期工作(发布者和订阅者的解耦),我需要一个消息传递系统。 Let's say I want to realize this with node.js (being fully aware that there are a lot quicker ways to get this done).假设我想用 node.js 来实现这一点(充分意识到有很多更快的方法可以完成这项工作)。

My "issue" or potentially just cognitive failure is to wrap my head around how to make sure that all subscribers received the message from the subject they subscribed to?我的“问题”或可能只是认知失败是围绕如何确保所有订阅者收到他们订阅的主题的消息?

The client/frontend sends an Event Request to the broker.客户端/前端向代理发送事件请求。 The broker potentially verifies the message and puts it on the intended queue.代理可能会验证消息并将其放入预期的队列中。 There are 2 microservices subscribed to this queue.有 2 个微服务订阅了此队列。 The broker is now just sending the oldest event on the queue with a callback to both microservices.代理现在只是发送队列中最旧的事件以及对两个微服务的回调。

Wouldn't this cause issues when one of the microservices is significantly slower than the other?当其中一个微服务明显慢于另一个时,这不会导致问题吗?

I mean, it should work as long as I don't want to send back acknowledgement messages that indicate the task is done by all subscribers.我的意思是,只要我不想发回表明任务已由所有订阅者完成的确认消息,它就应该工作。 The client doesn't know how many services were involved with the Event Request so it can't track it.客户端不知道事件请求涉及多少服务,因此无法跟踪它。 So it needs to be done by the broker.所以它需要由经纪人来完成。

Does that mean, I need to include that in a message broker?这是否意味着,我需要将其包含在消息代理中? That it keeps track of the subscribed services computing status of a given event?它会跟踪给定事件的订阅服务计算状态吗?

After more research and a few hours lying awake in bed I came to the conclusion that having multiple subscribers to one subject/topic should be considered bad practice if the publisher wants to receive responses/acknowledgements in order to keep track of the status of the sent request/message/event.经过更多研究并在床上醒着几个小时后,我得出的结论是,如果发布者想要接收响应/确认以跟踪已发送的状态,那么让多个订阅者订阅一个主题/主题应该被认为是不好的做法请求/消息/事件。

After a few more thoughts I came to the conclusion that multiple subscribing services to the same subject are most likely never necessary - at least in my scenario as long as I design the services properly.经过更多的思考后,我得出的结论是,对于同一主题的多个订阅服务很可能永远不需要 - 至少在我的场景中,只要我正确设计服务。 The only scenario I could think of was the addition of certain features at a later point in time without touching the already deployed service.我能想到的唯一方案是在稍后的时间点添加某些功能,而无需触及已经部署的服务。 This feels like a fix for an unsuitable service design.这感觉像是对不合适的服务设计的修复。

Then I thought how I could manage it anyways and came up with 3 approaches.然后我想我怎么能管理它并想出了3种方法。

First the standard structure一、标准结构

标准的发布-订阅结构No further explanation needed I suppose.我想不需要进一步的解释。 Don't mind the details with some of the methods, it's just a brainstormed version which is definitely not ideal.一些方法的细节不要介意,这只是一个头脑风暴的版本,绝对不理想。 It's enough to display the pattern.显示模式就足够了。

Approach 1 - Aggregator collects responses方法 1 - 聚合器收集响应

聚合器方法Since the Broker keeps track on every Subscriber it always knows (or can easily calculate) the number of responses to expect.由于代理跟踪每个订阅者,它总是知道(或可以轻松计算)预期响应的数量。 It therefore could redirect the response messages to an Aggregator Subject that gets automatically created when a message is being sent/published that needs a response or message of success (think of an update of some customer data - you obviously want to know that the message got through and successfully processed).因此,它可以将响应消息重定向到一个聚合器主题,该主题在发送/发布需要响应或成功消息的消息时自动创建(想想一些客户数据的更新 - 你显然想知道消息得到了通过并成功处理)。

Of course, the Aggregator could always be inbetween even if there's just one response coming back.当然,即使只有一个响应返回,聚合器也可能总是介于两者之间。 That'd reduce the amount of cases to cover.这将减少要覆盖的案件数量。 The Aggregator is basically some sort of proxy.聚合器基本上是某种代理。 It still adds complexity to the Broker though.尽管如此,它仍然增加了 Broker 的复杂性。

Approach 2 - Broker publishes acknowledge messages方法 2 - 代理发布确认消息

发布确认消息First of all: don't mind the mess with the connections on the right.首先:不要介意右边的连接混乱。 It works for me as a sketch but is far from tidy.它对我来说是一个草图,但远非整洁。

Every message that is being published is being answered with an acknowledge message by the Broker.正在发布的每条消息都会由 Broker 以确认消息来回答。 That message is being put on the messages individual subject stack.该消息被放置在消息单独的主题堆栈中。 Since the Broker knows how many Subscribers every Subject has, it can send back how many responses a Publisher should expect.由于 Broker 知道每个 Subject 有多少个订阅者,它可以发回一个 Publisher 应该期望多少个响应。 Acknowledge messages in general are also usefull to notify Publishers wether their message/event/request was accepted or not as well (think of a authentication and authorization pattern here).一般来说,确认消息也有助于通知发布者他们的消息/事件/请求是否被接受(在这里考虑身份验证和授权模式)。

This will work as long as the Publisher always wants a response.只要发布者始终需要响应,这将起作用。 If it doesn't messages could stick around for quite a while.如果它没有消息可能会停留很长一段时间。 A timeout could solve this.超时可以解决这个问题。

Approach 3 - Transport Protocol Responses方法 3 - 传输协议响应

传输协议响应This is very similar to approach 2 with the difference that the transport protocol is being used to inform the Publisher about the status of the sent request and the potential number of responses to expect.这与方法 2 非常相似,不同之处在于传输协议用于通知发布者有关已发送请求的状态和预期的潜在响应数量。

Since most if not all protocols suitable for this kind of topography offer some way of response messages and since those should be used anyway to verify that the message has been successfully sent in the first place, the answer could also contain a payload informing the client not only about the successful transfer but also about how many responses to expect.由于大多数(如果不是所有)适用于这种拓扑的协议都提供了某种方式的响应消息,并且无论如何都应该使用这些方式来验证消息是否已经成功发送,所以答案还可以包含一个有效负载,通知客户端不要仅与成功转移有关,还与预期的响应数有关。

Conclusion结论

I'd say the Aggregator approach is too much overhead and it needs more extra code than just using either the transport protocol or the message system itself.我想说聚合器方法的开销太大,它需要更多的额外代码,而不仅仅是使用传输协议或消息系统本身。 The Aggregator is interesting because the client can be entirely oblivious about the services and is therefore decoupled.聚合器很有趣,因为客户端可以完全忽略服务,因此是解耦的。

The usage of the message system is interesting for logging purposes as well (potential debugging) and the implementation of Sagas (chains of events).消息系统的使用对于日志记录(潜在的调试)和 Sagas 的实现(事件链)也很有趣。

Note笔记

I do not promote any of these approaches as being best practice.我不提倡将这些方法中的任何一种作为最佳实践。 I solely want to answer my own question with the results of my research.我只想用我的研究结果来回答我自己的问题。

As you have found out through your own thinking, it's hard to implement pub-sub/topic pattern using 1 queue, because then that 1 queue would have to keep track of the messages to every subscribers.正如您通过自己的思考发现的那样,使用 1 个队列很难实现 pub-sub/topic 模式,因为这样 1 个队列将不得不跟踪每个订阅者的消息。 That's a lot of responsibility for that 1 queue.这对 1 个队列有很大的责任。

Typically, the pub-sub/topic pattern, is implemented using several queues:通常,发布-订阅/主题模式是使用多个队列实现的:

  • One for incoming messages一个用于传入消息
  • One for each subscriber (susbscriber queues).每个订阅者(订阅者队列)一个。

The subscriber queue act as a mailbox for a specific address.订阅者队列充当特定地址的邮箱。 If you have 5 subscribers then you will have 5 subscriber queues.如果您有 5 个订阅者,那么您将有 5 个订阅者队列。

The broker will distribute the messages from the incoming queue to each subscriber queue depending on the configurated rate at which the subscriber queues are refilled.代理将根据重新填充订阅者队列的配置速率将消息从传入队列分发到每个订阅者队列。

This allows each queue to only deal with 1 specific subscriber and it's much easier to track what the subscriber has consumed with acknowledgements.这允许每个队列只处理 1 个特定的订阅者,并且更容易跟踪订阅者通过确认消费的内容。 Also, each subscriber is able to consume the messages in its subscriber queue at his own pace.此外,每个订阅者都可以按照自己的节奏使用其订阅者队列中的消息。

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

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