回复并不总是传递到所需的回复侦听器容器
Replies are not always delivered to the desired reply listener container
我们正在使用 spring-kafka 和 ReplyingKafkaTemplate 应用 request/reply 语义。
但是,我们注意到有时回复不会到达应有的位置。
以下是我们设置的粗略描述:
服务 A
2 个实例
使用来自具有 2 个分区的 topic-a
的消息。 (每个实例分配 1 个分区)。
服务A是发起者。
服务 B:
2 个实例,使用来自 topic-b
的消息,它也有 2 个分区。
使用 @SendTo
注释对来自 A 的传入消息和 returns 回复消息作出反应。
观察到的行为:
当服务 A 的实例,例如A1,正在向服务 B 发送消息,发送失败,回复超时。该请求被 B 成功使用并返回了一个回复,但是它被另一个实例使用了,例如A2。从日志中我可以看到 A1 得到 topic-a-0 分配,而 A2 得到 topic-a-1 分配。
来自文档的建议:
文档的这一部分描述了我们的场景:https://docs.spring.io/spring-kafka/reference/html/#replying-template
它给出了一些建议:
- 给每个实例一个专门的回复主题
- 使用回复分区header并为每个实例使用专用分区
我们的设置基于整个服务的单个主题。因此,所有传入事件和回复事件都发送到此主题并从该主题中使用。所以选项 #1 在我们的情况下是不可取的。
选项 #2 的缺点是您不能使用组管理功能,这很可惜,因为我们的服务 运行 在 Kubernetes 上,所以我们希望使用组管理功能以获得最大的灵活性。
第三种选择?
所以我想知道是否有第三种选择:
为什么不使用组管理并在发送消息时在运行时间动态确定回复容器的分配主题分区并设置回复分区header。
看起来 ReplyingKafkaTemplate#getAssignedReplyTopicPartitions 方法正好提供了这些信息。
这样,分区就不是固定的,我们仍然可以使用组管理功能。
我可以预见的唯一缺点是,在发送请求后但在收到回复之前重新平衡分区时,请求可能会失败。
我已经测试了一些东西,看看它是否有效,看起来确实有效。我post这个问题的主要原因是检查我的想法是否有意义,是否有任何注意事项需要考虑。我想知道为什么开箱即用的 spring-kafka 不支持它。
如果我的解决方案有意义,我愿意提出增强问题并在 spring-kafka 项目上提供 PR。
正如您所描述的,问题是不能保证我们会在重新平衡后获得相同的分区。
“第三个选项”是为每个实例使用不同的 group.id
并设置 sharedReplyTopic=true
。在这种情况下,所有实例都将收到回复,而未发送请求的实例将丢弃回复。
但是,最好的解决方案是为每个实例使用唯一的回复主题。
我们正在使用 spring-kafka 和 ReplyingKafkaTemplate 应用 request/reply 语义。 但是,我们注意到有时回复不会到达应有的位置。
以下是我们设置的粗略描述:
服务 A
2 个实例
使用来自具有 2 个分区的 topic-a
的消息。 (每个实例分配 1 个分区)。
服务A是发起者。
服务 B:
2 个实例,使用来自 topic-b
的消息,它也有 2 个分区。
使用 @SendTo
注释对来自 A 的传入消息和 returns 回复消息作出反应。
观察到的行为:
当服务 A 的实例,例如A1,正在向服务 B 发送消息,发送失败,回复超时。该请求被 B 成功使用并返回了一个回复,但是它被另一个实例使用了,例如A2。从日志中我可以看到 A1 得到 topic-a-0 分配,而 A2 得到 topic-a-1 分配。
来自文档的建议:
文档的这一部分描述了我们的场景:https://docs.spring.io/spring-kafka/reference/html/#replying-template 它给出了一些建议:
- 给每个实例一个专门的回复主题
- 使用回复分区header并为每个实例使用专用分区
我们的设置基于整个服务的单个主题。因此,所有传入事件和回复事件都发送到此主题并从该主题中使用。所以选项 #1 在我们的情况下是不可取的。
选项 #2 的缺点是您不能使用组管理功能,这很可惜,因为我们的服务 运行 在 Kubernetes 上,所以我们希望使用组管理功能以获得最大的灵活性。
第三种选择?
所以我想知道是否有第三种选择: 为什么不使用组管理并在发送消息时在运行时间动态确定回复容器的分配主题分区并设置回复分区header。 看起来 ReplyingKafkaTemplate#getAssignedReplyTopicPartitions 方法正好提供了这些信息。 这样,分区就不是固定的,我们仍然可以使用组管理功能。 我可以预见的唯一缺点是,在发送请求后但在收到回复之前重新平衡分区时,请求可能会失败。
我已经测试了一些东西,看看它是否有效,看起来确实有效。我post这个问题的主要原因是检查我的想法是否有意义,是否有任何注意事项需要考虑。我想知道为什么开箱即用的 spring-kafka 不支持它。
如果我的解决方案有意义,我愿意提出增强问题并在 spring-kafka 项目上提供 PR。
正如您所描述的,问题是不能保证我们会在重新平衡后获得相同的分区。
“第三个选项”是为每个实例使用不同的 group.id
并设置 sharedReplyTopic=true
。在这种情况下,所有实例都将收到回复,而未发送请求的实例将丢弃回复。
但是,最好的解决方案是为每个实例使用唯一的回复主题。