我们的代理正在接收大量消息(大约15-30 MB /秒),我们希望实时接收这些消息并进行一些处理。每条消息都是几百kB。
我们的处理管道使用线程池,因此我们希望从单次轮询中提取的记录包含大批消息,这样我们的线程池就不必频繁处理小批量并冒着以下风险:用完线程。目前,我们正在通过修改我们的Kafka Consumer的fetch.min.bytes
,receive.buffer.bytes
和max.partition.fetch.bytes
配置对此进行控制。
我们目前还没有一个可以将消息解复用到不同管道的单一使用者的能力。这样,我们将单个使用者分配到管道,而每个使用者都分配到其自己的组。
我们遇到的问题是,一旦开始摄取多个管道(每个管道在其自己的组中拥有自己的消费者),我们的摄取率就开始落后于生产者。有趣的是,当我们运行单个管道时,就不会出现滞后问题。我们的应用程序用于实时或近实时分析,因此最终,我们希望时滞为0或尽可能接近0。
配置使用者以使其在不同组中同时运行时,我们可以最大程度地减少延迟的最佳方法是什么?
答案 0 :(得分:0)
这可能指向配置问题。 Kafka旨在将数据尽快分发给使用者,前提是假设正在使用的消息仍在页面缓存中。如果它们不再在页面缓存中 ,则表示消息是在前一段时间产生的,现在它们仅存在于磁盘日志中,而不存在于页面缓存中,那么您肯定会发现速度变慢,因为Kafka必须去从磁盘读取日志,这比从内存读取要慢数千倍。
如果您不想处理小批量产品,除了要提到的已调整属性外,还应注意消费者调查的时间。 50ms或更高的时间应该足够。但是,我看到客户端使用1毫秒作为轮询间隔,这有效地减慢了使用速度,因为它不允许消费者有足够的时间来获取尽可能多的数据。
一项最终建议。不要在kafka使用者正在使用的同一线程上执行数据处理/验证。有时,人们在相同的使用者线程上执行昂贵的处理,而没有意识到这一点会减慢消耗。使用者线程应该只从Kafka抓取消息,理想情况下甚至不反序列化它们,而是抓取字节(或String,或任何序列化格式),然后将其转储到线程安全的队列中,在该队列中可以反序列化和处理该消息。 -线。这样可以确保使用线程可以尽快轮询,而仅受可用CPU的限制。
最后,在KafkaConsumer
的官方Javadoc上有很多很棒的建议和技巧:
https://kafka.apache.org/20/javadoc/org/apache/kafka/clients/consumer/KafkaConsumer.html