将事件发布到单个微服务实例
Publishing an Event to a Single Microservice Instance
我正在从事一个项目,该项目具有多个事件驱动的微服务,并且还使用 Kubernetes 进行负载平衡。所有的服务都是发布者和听众。当一个微服务发布一个事件时,所有的监听器都在捕捉这个事件(如果它监听了那个特定的事件)并完成他们的工作。在此之前,此流程没有问题:
假设我有一个负责发送电子邮件的微服务。由于高负载,该服务被负载均衡器复制了 2 次。现在我们有 3 个电子邮件服务实例。当发布 "sendMail" 事件时,所有 3 个实例都在捕获事件并为自己发送电子邮件。一天结束时,发送了 3 封电子邮件。
我的问题是,我能否配置一个允许我为两种场景发布事件的云总线。我想对一个事件说 "when a single listener catches you, disappear" 或 "go to every listener waiting out there".
例如;
微服务:A、B、C
被负载均衡器复制:A1、A2、A3、B1...
案例 1:我想为所有服务的实例发布一个事件。
案例二:我想为服务A实例发布一个事件。
案例 3:我想为 A 的单个实例发布一个事件(不要
关心哪个)。
我试过了;
为事件提供目的地,但所有实例都具有相同的总线名称,因为它们被复制为相同的。如果我 give/know 一个单一的实例总线名称,我不会使用它,因为那个 pod 可能会死。
活动发布;
applicationContext().publishEvent(
new customEvent(
this, // Source
busProperties().getId(), // Origin Service
null // Destination Service (null: all)
)
);
事件侦听器;
@Component
public class Listener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
Foo();
}
}
我相信这可以通过设置您的 consumerGroupId 来解决。您的应用程序的每个实例(电子邮件服务的每个微服务)都需要有一个唯一的 groupId,以便 rabbitmq 将请求发送到这些可用的唯一组中的任何一个。
Here is how it works
我现在明白了,这里是 Image Link i posted earlier. I'm sure you already know about it. It is a common issue and the best way is to use a redis acting as a "blocking" 机制。由于消息队列向所有消费者异步发送请求,我们不知道谁在接收和处理请求,但我们确保它不是由所有使用阻塞处理的。在进行任何操作之前,请检查块,如果不存在,则处理请求。
我找到并实施了部分解决方案,使用 Spring Cloud Stream 和 Spring Cloud Bus。我将 Cloud Stream 与自定义队列和组一起用于单个事件(第一个示例的 sentMail 事件)。当我通过 Cloud Stream 发送消息时,如果微服务的多个实例正在侦听消息,它们将像这样一个一个地接收消息:
正在发送消息:M1、M2、M3
监听A微服务实例:A1、A2
使用云总线:
A1收到M1、M2、M3
A2收到M1、M2、M3
使用 Cloud Stream(已定义自定义组):
A1收到M1、M3
A2收到M2
我正在从事一个项目,该项目具有多个事件驱动的微服务,并且还使用 Kubernetes 进行负载平衡。所有的服务都是发布者和听众。当一个微服务发布一个事件时,所有的监听器都在捕捉这个事件(如果它监听了那个特定的事件)并完成他们的工作。在此之前,此流程没有问题:
假设我有一个负责发送电子邮件的微服务。由于高负载,该服务被负载均衡器复制了 2 次。现在我们有 3 个电子邮件服务实例。当发布 "sendMail" 事件时,所有 3 个实例都在捕获事件并为自己发送电子邮件。一天结束时,发送了 3 封电子邮件。
我的问题是,我能否配置一个允许我为两种场景发布事件的云总线。我想对一个事件说 "when a single listener catches you, disappear" 或 "go to every listener waiting out there".
例如;
微服务:A、B、C
被负载均衡器复制:A1、A2、A3、B1...
案例 1:我想为所有服务的实例发布一个事件。
案例二:我想为服务A实例发布一个事件。
案例 3:我想为 A 的单个实例发布一个事件(不要 关心哪个)。
我试过了; 为事件提供目的地,但所有实例都具有相同的总线名称,因为它们被复制为相同的。如果我 give/know 一个单一的实例总线名称,我不会使用它,因为那个 pod 可能会死。
活动发布;
applicationContext().publishEvent(
new customEvent(
this, // Source
busProperties().getId(), // Origin Service
null // Destination Service (null: all)
)
);
事件侦听器;
@Component
public class Listener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
Foo();
}
}
我相信这可以通过设置您的 consumerGroupId 来解决。您的应用程序的每个实例(电子邮件服务的每个微服务)都需要有一个唯一的 groupId,以便 rabbitmq 将请求发送到这些可用的唯一组中的任何一个。
Here is how it works
我现在明白了,这里是 Image Link i posted earlier. I'm sure you already know about it. It is a common issue and the best way is to use a redis acting as a "blocking" 机制。由于消息队列向所有消费者异步发送请求,我们不知道谁在接收和处理请求,但我们确保它不是由所有使用阻塞处理的。在进行任何操作之前,请检查块,如果不存在,则处理请求。
我找到并实施了部分解决方案,使用 Spring Cloud Stream 和 Spring Cloud Bus。我将 Cloud Stream 与自定义队列和组一起用于单个事件(第一个示例的 sentMail 事件)。当我通过 Cloud Stream 发送消息时,如果微服务的多个实例正在侦听消息,它们将像这样一个一个地接收消息:
正在发送消息:M1、M2、M3
监听A微服务实例:A1、A2
使用云总线:
A1收到M1、M2、M3
A2收到M1、M2、M3
使用 Cloud Stream(已定义自定义组):
A1收到M1、M3
A2收到M2