我们正在使用带有ReplyingKafkaTemplate的spring-kafka应用请求/答复语义。 但是,我们注意到,有时回复不会以应有的方式结束。
服务A
2个实例
消耗来自topic-a
的消息,该消息有2个分区。 (每个实例分配1个分区)。
服务A是发起方。
服务B:
2个实例使用topic-b
的消息,该消息也有2个分区。
对来自A的传入消息做出反应,并使用@SendTo
批注返回回复消息。
服务A的实例时,例如A1,正在向服务B发送消息,发送失败,并带有回复超时。 B成功使用了该请求,并返回了一个回复,但是另一个实例(例如, A2。从日志记录中,我可以看到A1被分配了topic-a-0,而A2被分配了topic-a-1。
我们在本节的文档中介绍了我们的方案:https://docs.spring.io/spring-kafka/reference/html/#replying-template 它给出了一些建议:
我们的设置基于整个服务的单个主题。因此,所有传入事件和回复事件都发送到此主题并从该主题中使用。因此,在我们的情况下,选项#1是不理想的。
选项#2的缺点是您不能使用组管理功能,这很可惜,因为我们的服务在Kubernetes上运行,因此我们希望使用组管理功能来获得最大的灵活性。
所以我想知道是否还有第三种选择: 为什么不使用组管理,并在发送消息并设置回复分区标头时在运行时即时确定回复容器的已分配主题分区。 看来ReplyingKafkaTemplate#getAssignedReplyTopicPartitions方法确实提供了此信息。 这样,分区不是固定的,我们仍然可以使用组管理功能。 我唯一可以预见的缺点是,在发送请求之后但在收到回复之前重新分区,则请求可能会失败。
我已经测试过一些东西,看它是否有效,看起来是否确实如此。我发布此问题的主要原因是检查我的想法是否合理,是否有任何注意事项需要考虑。我想知道为什么spring-kafka不支持此功能。
如果我的解决方案有意义,我愿意提出一个增强问题并提供spring-kafka项目的PR。
答案 0 :(得分:1)
您所描述的问题是,不能保证在重新平衡后我们将获得相同的分区。
“第三种选择”是为每个实例使用不同的group.id
并设置sharedReplyTopic=true
。在这种情况下,所有实例都将获得答复,并且将被未发送请求的实例丢弃。
但是,最好的解决方案是为每个实例使用唯一的答复主题。