Kafka使用过程中遇到的一些问题

  最近工作中需要一个日志收集系统,使用了kafka来实现。日志收集系统主要功能是,producer将接收到的logs存储到kafka里,然后consumer从kafka里边取数据进行消费处理。由于没有接触过kafka,在使用中遇到了一些问题,在此做个记录。

1. consumer有时候可以消费到日志,有时候却消费不到?

  Kafka配置情况:

  • 两个consumer group,每个group中只有一个consumer实例。(不是配置的,应该是应用程序为每个consumer group只创建了一个consumer实例??)
  • 一个topic,只配置了一个partition。

  问题:

  两个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?

2. 两台设备上只有一个上存在logs

  Kafka配置情况:

  • 一个topic,配置了四个partition。
  • 两个consumer group,每个group中只有一个consumer实例。(应该是应用程序为每个consumer group只创建了一个consumer实例)

  问题:

  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的策略如下:

  1. 判断消息中的partition字段是否有值,有值的话即指定了分区,直接将该消息发送到指定的分区就行。
  2. 如果没有指定分区(partition),则使用分区器进行分区路由,首先判断消息中是否指定了key。
  3. 如果指定了key,则使用该key进行hash操作,并转为正数,然后对topic对应的分区数量进行取模操作并返回一个分区。
  4. 如果没有指定key,则通过先产生随机数,之后在该数上自增的方式产生一个数,转为正数之后对分区数量进行取余操作,得到一个分区。

  由于在日志收集程序中Producer发送记录的时候指定了固定的key,根据这个key进行分区路由总是会选择同一个分区,所有日志都被发送给了同一个分区,因此只有关联这个分区的consumer实例才能消费,只有此consumer实例所在的server上才有日志文件。

 参考链接:

  https://blog.csdn.net/abinge317/article/details/84542073

猜你喜欢

转载自www.cnblogs.com/leaves1024/p/11073191.html