Java 将事件发布到单个Microservice实例

Java 将事件发布到单个Microservice实例,java,spring-boot,kubernetes,spring-cloud,Java,Spring Boot,Kubernetes,Spring Cloud,我正在从事一个项目,该项目有几个事件驱动的微服务,还使用Kubernetes进行负载平衡。所有服务都是发布者和侦听者。当微服务发布事件时,所有侦听器都在捕获事件(如果它侦听特定事件)并执行其工作。在此之前,此流程没有问题: 比如说,我有一个负责发送电子邮件的微服务。由于高负载,负载平衡器将此服务复制了2次。现在我们有3个电子邮件服务实例。发布“sendMail”事件时,所有3个实例都将捕获该事件并发送自己的电子邮件。在一天结束时,将发送3封电子邮件 我的问题是,我是否可以配置一个云总线,允许我发

我正在从事一个项目,该项目有几个事件驱动的微服务,还使用Kubernetes进行负载平衡。所有服务都是发布者和侦听者。当微服务发布事件时,所有侦听器都在捕获事件(如果它侦听特定事件)并执行其工作。在此之前,此流程没有问题:

比如说,我有一个负责发送电子邮件的微服务。由于高负载,负载平衡器将此服务复制了2次。现在我们有3个电子邮件服务实例。发布“sendMail”事件时,所有3个实例都将捕获该事件并发送自己的电子邮件。在一天结束时,将发送3封电子邮件

我的问题是,我是否可以配置一个云总线,允许我发布这两种场景的事件。我想对一个事件说“当一个听者抓住你,消失”或者“去找每一个等待你的听者”

比如,

微服务:A、B、C

负载平衡器复制:A1、A2、A3、B1

案例1:我想为所有服务的实例发布一个事件

案例2:我想为服务A实例发布一个事件

案例3:我想为单个实例发布一个事件(不要 不管哪个)

我试过了; 为事件提供目的地,但所有实例都具有相同的总线名称,因为它们被复制为相同的。如果我给出/知道单个实例总线名称,我不会使用它,因为pod可能会死掉

事件发布

applicationContext().publishEvent(
新定制活动(
这,//来源
busProperties().getId(),//源服务
null//目标服务(null:all)
)
);
事件监听器

@组件
公共类侦听器实现ApplicationListener{
@凌驾
ApplicationEvent(CustomEvent)上的公共无效{
Foo();
}
}

我相信这可以通过设置您的consumerGroupId来解决。应用程序的每个实例(电子邮件服务的每个微服务)都需要具有唯一的groupId,以便rabbitmq将请求发送到这些可用的唯一组中的任何一个


我现在更明白了,这是我之前发布的。我相信你已经知道了。这是一个常见的问题,最好的方法是使用redis作为“”机制。由于消息队列正在异步地向所有使用者发送请求,因此我们不知道谁在接收和处理请求,但我们可以确保不会使用阻塞来处理所有使用者的请求。在执行任何操作之前,请检查该块,如果它不存在,请处理该请求

我已经找到并实现了一个部分解决方案,使用SpringCloudStream和SpringCloudBus。我将云流与单个事件的自定义队列和组一起使用(第一个示例是sentMail事件)。当我通过云流发送消息时,如果一个微服务的多个实例正在侦听该消息,则它们会像这样逐个接收该消息:

发送消息:M1、M2、M3

监听微服务实例:A1、A2

使用云总线:

A1接收M1、M2、M3

A2接收M1、M2、M3

使用云数据流(已定义自定义组):

A1接收M1,M3

A2接收平方米


对于实现:

您使用什么作为此总线?KubeMQ?RabbitMQ但我不想解决这个问题,因为RabbitMQ是特定的,我正在寻找一个框架级别的解决方案。我明白了,您可以包括一个辅助消息确认主题,在这个主题中,任何侦听器都会立即发布自己的带有消息id的侦听事件。尽管这有风险,但会存在竞争条件,如果某些服务重新启动,它将继续读取过去的消息,您可能需要将这些读取的消息id存储在某个缓存中?替换所有代理中已经存在的功能(我认为)会变得非常混乱,或者您可以将
侦听器
模块提取为单独的单个服务,并将读取的消息提供给a、B、,我觉得必须有一个属性/配置来指定当单个侦听器使用事件时要删除的事件。那将很容易解决我的问题。但如果我找不到它,我不想要任何混乱的解决方案。我已经可以用autowired RabbitTemplate将一个事件发布为P2P,我想我可能会使用这个解决方案,我不想要,但也不混乱。首先,你共享的图像不可用,你能检查一下吗?(可能是我公司的网络政策阻止了它,我不知道)。我用我的las句子提到了这个解决方案。假设我们有3个A(A1、A2、A3)实例,每个实例都有自己的groupId。您说我必须通过提供特定的groupId来发布事件。例如A1,但如果A1维修吊舱死亡会发生什么?如果A1死亡,A2或A3应该捕获事件并执行必要的工作,这就是为什么我不能给出固定的总线名称。由于一些问题或版本更新,POD不断/最终消亡,重新启动。