与producer不同,消费者不会再new的时候创建tcp链接。
生产者入口类KafkaProducer在new的时候,会在后台默默地启动一个Sender线程,这个Sender线程负责Socket连接的创建(缺点:Java构造函数中启动线程,会造成this指针的逃逸,这始终是一个隐患。)。
TCP连接是在调用KafkaConsumer.poll方法时被创建的
创建时机:
01、发起FindCoordinator请求时
还记得消费者端有个组件叫协调者(Coordinator)吗?它驻留在Broker端的内存中,负责消费者组的组成员管理和各个消费者的位移提交管理。当消费者程序首次启动调用poll方法时,它需要向Kafka集群发送一个名为FindCoordinator的请求,希望Kafka集群告诉它哪个Broker是管理它的协调者。
不过,消费者应该向哪个Broker发送这类请求呢?理论上任何一个Broker都能回答这个问题,也就是说消费者可以发送FindCoordinator请求给集群中的任意服务器。在这个问题上,社区做了一点点优化:消费者程序会向集群中当前负载最小的那台Broker发送请求。负载是如何评估的呢?其实很简单,就是看消费者连接的所有Broker中,谁的待发送请求最少。当然了,这种评估显然是消费者端的单向评估,并非是站在全局角度,因此有的时候也不一定是最优解。不过这不并影响我们的讨论。总之,在这一步,消费者会创建一个Socket连接。
02、连接协调者时。
Broker处理完上一步发送的FindCoordinator请求之后,会返还对应的响应结果(Response),显式地告诉消费者哪个Broker是真正的协调者,因此在这一步,消费者知晓了真正的协调者后,会创建连向该Broker的Socket连接。只有成功连入协调者,协调者才能开启正常的组协调操作,比如加入组、等待组分配方案、心跳请求处理、位移获取、位移提交等。
03、消费数据时。
消费者会为每个要消费的分区创建与该分区领导者副本所在Broker连接的TCP。举个例子,假设消费者要消费5个分区的数据,这5个分区各自的领导者副本分布在4台Broker上,那么该消费者在消费时会创建与这4台Broker的Socket连接。
如何关闭TCP链接?
主动关闭和Kafka自动关闭
主动关闭:显式地调用消费者API的方法去关闭消费者,具体方式就是手动调用KafkaConsumer.close()方法,或者是执行Kill命令
自动关闭:由消费者端参数connection.max.idle.ms控制的,该参数现在的默认值是9分钟,即如果某个Socket连接上连续9分钟都没有任何请求“过境”的话,那么消费者会强行“杀掉”这个Socket连接。