我是Kafka的新手。我遇到以下情况, 我有入站和出站Kafka队列。 App从入站队列中读取消息,对其进行处理(调用10个下游服务),成功后,它将消息放入出站队列,然后将消息提交到入站队列。
WARN [kafka-coordinator-heartbeat-thread] [Consumer clientId=604dd51a-9b36-4490-aa80-51125bafb465, groupId=abc] This member will leave the group because consumer poll timeout has expired. This means the time between subsequent calls to poll() was longer than the configured max.poll.interval.ms, which typically implies that the poll loop is spending too much time processing messages. You can address this either by increasing max.poll.interval.ms or by reducing the maximum size of batches returned in poll() with max.poll.records.
INFO [kafka-coordinator-heartbeat-thread] - [Consumer clientId=604dd51a-9b36-4490-aa80-51125bafb465, groupId=abc] Member 604dd51a-9b36-4490-aa80-51125bafb465-e0 sending LeaveGroup request to coordinator zk2-abc.com:9092 (id: 214748 rack: null)
我面临两个问题,
我了解建议的解决方案是将“ max.poll.interval.ms”设置为处理消息所需的时间,但是我知道当情况良好时的处理时间,但不确定我的硬依赖性何时失败,因为我必须等待相关服务响应(重试)。我可以将可用时间设置为最大,但不能确定这是否是一种好方法,以及在卡夫卡级别的含义是什么。
我尝试过的
我想了解我必须处理什么解决方案,以解决上述问题以及每个问题的利弊。
答案 0 :(得分:1)
您可以创建另一个专门用于消息处理的线程,因此使用方线程永远不会在调用poll()
时延迟。
您可以创建一个pool
处理线程(足够大,在分配新消息时不会降低使用者线程的速度),也可以将内部压力保存在内部结构中,例如{{1} }或某种大小有限的同步ConcurrentHashMap
。您的“处理器”线程将完成艰苦的工作,因此使用者可以及时调用Deque/Queue
。
希望它会有所帮助,将其写成锈蚀!
这取自Kafka消费者documentation:
我们有意避免实现特定的线程 处理模型。这为实现留下了几种选择 记录的多线程处理。
- 每个线程一个使用者
一个简单的选择是为每个线程提供自己的使用者实例。这是此方法的优缺点: PRO:这是最容易实现的PRO:通常是最快的,因为没有 需要线程间协调PRO:它可以按顺序进行处理 基于每个分区非常容易实现(每个线程仅 按照收到消息的顺序处理消息)。缺点:更多的消费者 意味着到群集的更多TCP连接(每个线程一个)。一般来说 Kafka非常有效地处理连接,因此通常 成本低。缺点:多个使用者意味着更多请求被发送到 服务器和少量的数据批处理可能会导致一些 I / O吞吐量下降。 CON:所有线程的总线程数 进程将受分区总数的限制。
- 使消费与加工脱钩
另一种选择是让一个或多个使用者线程完成所有数据消耗和操作 将ConsumerRecords实例关闭到池消耗的阻塞队列中 实际处理记录处理的处理器线程数。这个 该选项同样具有优点和缺点:PRO:此选项允许 独立缩放使用者和处理器的数量。这个 使得有一个单一的消费者可以为许多处理器提供食物 线程,避免对分区进行任何限制。缺点:保证 跨处理器的顺序需要特别小心,因为线程 将独立执行之前可能实际上是 由于线程的运气,在稍后的数据块之后进行了处理 执行时间。对于无订购要求的处理 这不是问题。缺点:手动提交职位成为 更加困难,因为它要求所有线程进行协调以确保 该分区的处理已完成。有很多可能 这种方法的变化。例如,每个处理器线程可以 有自己的队列,使用者线程可以哈希到这些队列中 使用TopicPartition进行排队,以确保按顺序消费和 简化提交。