为微服务扩展Kafka
问题
我想了解我需要如何设计微服务的消息传递以使其仍然具有弹性和可扩展性。
目标
- 微服务允许弹性数量的实例根据当前负载自动伸缩。这个特性不应该被Kafka限制。
- 我们需要保证至少一次交付
- 我们需要保证涉及同一实体的事件的传递顺序
运行示例
- 简单地说,假设有 2 个微服务 A 和 B;
- A1、A2为微服务A的实例;微服务B的B1和B2实例
- A1 和 A2 发布描述 A 实体上的 CRUD 操作的事件,例如实体被创建、更新、删除。
设计一
- A1 在主题下发布事件,
a.entity.created包括id在消息正文中创建的实体的信息。 - A1 必须指定将有多少个分区 (p) 以允许消费者并行消费。这将允许可扩展性。
- B1 和 B2
a.entity.created作为消费群体订阅该主题b-consumers。这导致 B 的实例之间的负载分布。
问题:
- a) 涉及同一实体的事件可能会被并行处理并且可能会出现乱序,对吗?
- b) 这将导致 B 的实例并行处理请求。限制因素是生产者如何定义 p(分区数量)。如果有 5 个分区,但我需要 8 个消费者来应对负载,那么它将无法工作,因为 3 个消费者不会收到事件。我理解正确吗?这将 IMO 无法用于可能想要进一步扩展的弹性微服务。
设计二
- A1 在
a.entity.created.{entityId}导致许多不同主题的主题下发布事件。 - 每个分区大小设置为 1。
- B1 和 B2
a.entity.created.*使用通配符作为消费者组订阅主题b-consumers。这导致 B 的实例之间的负载分布。
问题:
- c) 同一实体的事件应该保证按顺序传递,因为只有一个分区,对吗?
- d) 这里是如何处理可扩展性的?分区的数量不应该限制消费者的数量,或者是吗?
e) 是否有更好的方法来保证上述目标?
设计 III(感谢 StuartLC)
- A1根据entityId在topic
a.entity.created和partition key下发布事件。 - 每个分区大小设置为 10。
- B1 和 B2
a.entity.created作为消费群体订阅该主题b-consumers。这导致 B 实例之间的负载分布。由于分区键,关于同一实体的事件将按顺序传递。
问题:
- f) 当 p=10 时,我最多可以有 10 个消费者。这意味着如果使用环境变量,我必须在设计时/部署时估计消费者的数量。我可以将它移动到运行时以便动态调整吗?