我们使用 Kafka 作为微服务之间的消息传递系统。我们有一个 kafka 消费者监听一个特定的主题,然后将数据发布到另一个主题中,由 Kafka Connector 接收,Kafka Connector 负责将其发布到某些数据存储中。
我们使用 Apache Avro 作为序列化机制。
我们需要启用 DLQ 来为 Kafka Consumer 和 Kafka Connector 添加容错能力。
由于多种原因,任何消息都可能转移到 DLQ:
- 格式错误
- Bad Data
- 对大量消息进行限制,因此某些消息可能会移至 DLQ
- 由于连接问题,发布到数据存储失败。
对于上述第 3 点和第 4 点,我们想再次从 DLQ 重试消息。
同样的最佳实践是什么。请指教。
仅推送导致不可重试错误的 DLQ 记录,即:示例中的点 1(格式错误)和点 2(数据错误)。对于 DLQ 记录的格式,一个好的方法是:
- 将与原始记录完全相同的 kafka 记录值和密钥推送到 DLQ,不要将其包装在任何类型的信封内。这使得在故障排除期间使用其他工具重新处理变得更加容易(例如使用新版本的解串器等)。
- add a bunch of Kafka header to communicate meta-data about the error, a few typical examples would be:
- 该记录的原始主题名称、分区、偏移量和 Kafka 时间戳
- 异常或错误消息
- 未能处理该记录的应用程序的名称和版本
- 错误发生时间
通常,我为每个服务或应用程序使用一个 DLQ 主题(不是每个入站主题使用一个 DLQ 主题,也不是跨服务共享的主题)。这往往会使事情保持独立且易于管理。
哦,您可能想对 DLQ 主题的入站流量进行一些监控和警报;)
恕我直言,第 3 点(高容量)应该通过某种自动缩放来处理,而不是通过 DLQ 来处理。尝试始终高估(稍微)输入主题的分区数量,因为您可以启动服务的最大实例数量受此限制。过多的消息不会使您的服务超载,因为 Kafka 消费者在决定时会显式轮询更多消息,因此他们请求的消息永远不会超出应用程序可以处理的范围。如果出现消息高峰,会发生什么,它们会继续堆积在上游 kafka 主题中。
应直接从源主题重试第 4 点(连接),而不涉及任何 DLQ,因为错误是暂时的。将消息丢弃到 DLQ 并拾取下一条消息并不能解决任何问题,因为连接问题仍然存在,并且下一条消息也可能会被丢弃。读取或不读取来自 Kafka 的记录并不会使其消失,因此存储在那里的记录以后很容易再次读取。您可以对服务进行编程,使其仅在成功将结果记录写入出站主题时才前进到下一个入站记录(请参阅 Kafka 事务:读取主题实际上涉及到write操作,因为新的消费者偏移量需要被持久化,所以你可以告诉你的程序将新的偏移量和输出记录作为同一原子事务的一部分持久化)。
Kafka 更像是一个存储系统(只有 2 个操作:顺序读取和顺序写入),而不是消息队列,它擅长持久化、数据复制、吞吐量、规模……(……还有炒作;))。它往往非常适合将数据表示为事件序列,如“事件溯源”。如果此微服务设置的需求主要是异步点对点消息传递,并且如果大多数场景宁愿支持超低延迟并选择丢弃消息而不是重新处理旧消息(如列出的 4 点所示),也许像Redis队列这样的有损内存队列系统更合适吗?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)