最近工作中需要一个日志收集系统,使用了kafka来实现。日志收集系统主要功能是,producer将接收到的logs存储到kafka里,然后consumer从kafka里边取数据进行消费处理。由于没有接触过kafka,在使用中遇到了一些问题,在此做个记录。
Kafka配置情况:
问题:
两个consumer group都用来消费唯一的topic,测试时发现,在有时候,consumer1(属于consumer group1)有消费,consumer2(属于consumer group2)却没有消费。Topic有一个partition,两个consumer group都只有一个consumer 实例,为什么会存在consumer没有消费的情况?
分析:
查看程序log发现,在存在问题的时候,consumer1分配到了partition,consumer2却没有分配到partition,从而导致只有consumer1有消费,consumer2没有消费。为什么consumer2没有分配到partition,这实在令人费解!
原来,之前在服务器上测试时已经运行了此程序,在本地主机进行测试时又运行了一个,即服务器和本地主机同时运行了此日志收集程序,虽然每个consumer group只配置了一个consumer实例,但是服务器和本地主机同时存在group ID相同的consumer,实质上导致了每个consumer group有两个consumer实例,只是这两个consumer实例位于不同的设备上。
Consumer group下的consumer实例是可以位于不同的设备上的,官网有一段话可以体现这一点:
Consumers label themselves with a consumer group name, and each record published to a topic is delivered to one consumer instance within each subscribing consumer group. Consumer instances can be in separate processes or on separate machines.
在kafka中,每个consumer实例都有一个group ID用于标识它是属于哪一个group,group ID相同的各个consumer实例都属于同一个consumer group。本地主机程序中存在的consumer2(属于consumer group2的consumer)与服务器程序中的consumer2拥有同一个group ID,因此属于同一个group,而topic只有一个partition,因此这两个consumer只能有一个能够分配到这个partition进行消费。关闭服务器上的程序后,一切就恢复了正常。
???consumer实例并不是位于本地主机程序或服务器程序,只是本地主机程序或服务器程序调用kafka API各自创建了一个consumer?
Kafka配置情况:
问题:
consumer消费时,会将接收到的日志写入服务器磁盘文件中。有两台服务器都在运行日志收集程序,因此每个服务器都会存储日志文件。但是在测试时发现,所有日志都只存在于server1上,而server2上没有日志,即便使用测试工具发送了大量数据,server2仍然没有日志。
分析:
查看log发现,server1上的consumer分配的partition为partition_0 partition_1,server2上的consumer分配的partition为partition_3、partition_4,server2上的程序一直没有消费因而没有日志数据,这就说明所有数据都被producer发送到此topic的partition_1或partition_2上,这应该是与生产者的分区路由导致的,因此有必要了解下生产者的分区策略。
Kafka中的每个Topic分配了4个Partition,生产者(Producer)在将消息记录(ProducerRecord)发送到某个Topic时是要选择对应的Partition的,选择Partition的策略如下:
由于在日志收集程序中Producer发送记录的时候指定了固定的key,根据这个key进行分区路由总是会选择同一个分区,所有日志都被发送给了同一个分区,因此只有关联这个分区的consumer实例才能消费,只有此consumer实例所在的server上才有日志文件。
参考链接:
https://blog.csdn.net/abinge317/article/details/84542073
原文:https://www.cnblogs.com/leaves1024/p/11073191.html