kafka Java consumer设计原理

设计原理

  首先,kafka Java consumer是单线程的设计。准确来说是双线程,从kafka 0.10.1.0版本开始kafkaConsumer变成了用户主线程和心跳线程的双线程设计。
  所谓用户主线程,就是你启动Consumer应用程序的main方法的那个线程。而心跳线程(Heartbeat Thread)只负责定期发送心跳给对应的Boroker,以标识消费者应用的存活性。引入心跳线程的目的还有一个:解耦真实的消息处理逻辑与消费者组成员存活性管理。
  尽管多了一个心跳线程,但是实际的消息处理还是由主线程完成。所以我们还是可以认为KafkaConsumer是单线程设计的。

为什么用单线程设计

  在kafka consumer老版本中,是多线程设计的。阻塞式的设计。
采用单线程设计的原因:

  1. 新版本Consumer设计了单线程+轮询的机制。这种设计能够较好的实现非阻塞式的消息获取。
  2. 单线程的设计能够简化Consumer端的设计,将处理消息的逻辑是否使用多线程的选择,交由你来决定。
  3. 不论使用那种编程语言,单线程的设计都比较容易实现。并且,单线程设计的Consumer更容易移植到其它语言上。

多线程方案:

  我们要明确,kafkaConsumer类不是线程安全的。所有的网络I/O处理都发生在用户主线程中。所以,你使用时必须保证线程安全。也就是,你不能在多个线程中共享一个KafkaConsumer实例,否则会抛出ConcurrentModificationException异常。

方案一:

  消费者程序启动多个线程,每个线程维护专属的KafkaConsumer实例,负责完整的消费获取,消费处理流程
在这里插入图片描述

方案二:

  消费者程序使用单或者多线程获取消息,同时创建多个消费线程执行消息处理逻辑。获取消息的线程可以是一个,也可以是多个,每个线程维护专属的KafkaConsumer实例,处理消息则交由特定的线程池来做。从而实现消息获取与消息处理的真正解耦。
在这里插入图片描述

两个方案的优缺点:

在这里插入图片描述
解释:
方案一:
第二个缺点:它是启动的多个线程,每个线程维护一个Consumer实例,由于:一个主题的一个分区只能由消费者组的一个实例消费,所以该方案的线程数与分区是有关联的,创建多于分区数的线程是无用的。所以可扩展性比较差。
方案二:
第二个缺点:因为它的消息获取与消息处理是分开进行的,消息处理是使用的线程池。所以它的消息的顺序是不能保证的,如果你对消息的顺序有要求,那不建议使用方案2。
第三个缺点:因为它的处理链路加长,所以也就导致位移的提交比较难以管理,所以可能出现重复消费,如果你对此处有比较强的要求,不建议使用方案2。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐