可靠的火灾忘记卡夫卡生产者实施战略

时间:2017-05-31 15:28:04

标签: apache-kafka message-queue messaging reliability producer

我和Kafka在1英里的问题中间。每个人都处理分区等,但如何处理第1英里?

我的系统由许多生成分布在节点上的事件的应用程序组成。我需要将这些事件传递给一组以可靠/故障安全方式充当消费者的应用程序。选择的消息传递系统是Kafka(由于它的日志性质),但它不是一成不变的。

事件应尽可能以分离的方式传播。这意味着生产者应该对可靠传递信息负全部责任。这意味着制作活动的应用程序根本不用担心事件传递。

制作人的可靠性架构必须考虑到:

  • 盒子连接中断 - 在停电期间生产者根本无法访问网络;因此无法访问Kafka集群
  • 框重启 - 生产者和事件生成应用重启(独立);生产者应该持续发送消息(在重试,批处理等过程中)。
  • 内部Kafka例外 - 邮件大小过大;序列化异常;等

到目前为止,我所检查的图书馆都没有涵盖这些案例。是否有建议的策略如何解决这个问题?

我知道在制作人send()期间有可重复的不可重试的错误。在那些可重复的,图书馆通常内部处理一切。但是,不可重复的结束在异步回调中有例外......

我应该盲目地将这些重播到无穷大吗?对于网络中断它应该工作,但卡夫卡内部错误如何 - 说消息太大。可能存在 DeadLetterQueue 类似机制+重播。但是,如何处理消息计数...

关于持久性 - 轻量级数据库后端应该解决这个问题。只需创建持久队列,然后删除已发送/已确认的队列。但是,我担心如果这很简单,很久以前它就已经在标准的Kafka库中实现了。表演可能会走向南方。

看到KAFKA-3686KAFKA-1955之类的内容让我有点担心。

提前致谢。

1 个答案:

答案 0 :(得分:2)

我们有一个生产系统,其主要用例是可靠的消息传递。我不能详细介绍,但是我可以分享一个关于如何实现这一目标的高级设计。然而,这个系统保证“至少一次交付”的消息传递信息。

enter image description here

来源

  • 首先我们设计了一个消息模式,并将所有消息发送给它 系统必须遵循它。
  • 然后我们将消息写入一个mysql消息表,该消息表由分片组成 日期,标记为已交付的字段
  • 我们有一个应用程序不断轮询数据库,行标记为未交付,拾取行,构造消息并将其发送到负载均衡器,这是一个阻塞调用, 仅在返回200时才更新要传递的消息行    如果是5xx,应用程序将重新启动睡眠状态的消息。您也可以根据需要对重试进行配置。
  

每个源系统都维护自己的轮询应用程序和db。

制作人数组

  • 这基本上是一个负载均衡器下的机器数组,等待传入消息并将其生成到Kafka集群。
  • 我们维护每个主题的3个副本,并且在生产者Config中我们保持acks = -1,这对于你的fire-n-forget要求非常重要。按照文档
  

acks = all这意味着领导者将等待全套同步   复制品以确认记录。这保证了记录   只要至少有一个同步副本仍然存在,就不会丢失   活。这是最强有力的保证。这是等效的   到acks = -1设置

  • 正如我所说,production是一个阻塞调用,如果消息在所有3个副本中成功生成,它将返回2xx。 4xx,如果消息不符合架构要求 5xx,如果kafka经纪人抛出一些例外。

消费者数组

  • 这是一个正常的机器阵列,为主题的消费者群体运行Kafka高级消费者。

我们目前正在运行此设置,其中几个附加组件用于生产中的其他一些功能流程,从源头来看,它基本上是不可忘记的。

该系统解决了您的所有问题。

  1. 框连接中断:除非源轮询应用获得2xx,否则 将再次产生,这可能导致重复。

  2. 框重启:由于源的重试机制,这也不应该是一个问题。

  3. 内部Kafka异常:通过轮询应用程序小心,因为生产者数组将回复5xx无法生成,并将进一步重试。

  4. Acks = -1,也确保所有副本都是同步的并且拥有该消息的副本,因此代理停止也不会成为问题。