13 | Java生产者是如何管理TCP连接的?


Kafka 核心技术与实战

客户端实践及原理剖析

13 | Java生产者是如何管理TCP连接的?

为何采用 TCP?

Apache Kafka 的所有通信都是基于 TCP 的,而不是基于 HTTP 或其他协议。原因在于:

  • 从社区的角度来看,在开发客户端时,人们能够利用 TCP 本身提供的一些高级功能,比如多路复用请求以及同时轮询多个连接的能力。

所谓的多路复用请求,即 multiplexing request,是指将两个或多个数据流合并到底层单一物理连接中的过程。TCP 的多路复用请求会在一条物理连接上创建若干个虚拟连接,每个虚拟连接负责流转各自对应的数据流。

  • 目前已知的 HTTP 库在很多编程语言中都略显简陋。

基于这两个原因,Kafka 社区决定采用 TCP 协议作为所有请求通信的底层协议。

Kafka 生产者程序概览

开发一个生产者的步骤有 4 步:

  • 第 1 步:构造生产者对象所需的参数对象。
  • 第 2 步:利用第 1 步的参数对象,创建 KafkaProducer 对象实例。
  • 第 3 步:使用 KafkaProducer 的 send 方法发送消息。
  • 第 4 步:调用 KafkaProducer 的 close 方法关闭生产者并释放各种系统资源。
Properties props = new Properties ();
props.put(“参数1, “参数1的值”);
props.put(“参数2, “参数2的值”);
……
try (Producer<String, String> producer = new KafkaProducer<>(props)) {
            producer.send(new ProducerRecord<String, String>(……), callback);
  ……
}
何时创建 TCP 连接?

就上面的那段代码而言,可能创建 TCP 连接的地方有两处:Producer producer = new KafkaProducer(props) 和 producer.send(msg, callback)。

在创建 KafkaProducer 实例时,生产者应用会在后台创建并启动一个名为 Sender 的线程,该 Sender 线程开始运行时首先会创建与 Broker 的连接。

如果不调用 send 方法,Producer 都不知道给哪个主题发消息,它又怎么能知道连接哪个 Broker 呢?答案是连接 bootstrap.servers 参数指定的所有 Broker

bootstrap.servers 参数是 Producer 的核心参数之一,指定了这个 Producer 启动时要连接的 Broker 地址。

在实际使用过程中,不建议把集群中所有的 Broker 信息都配置到 bootstrap.servers 中,通常指定 3~4 台就足以了。因为 Producer 一旦连接到集群中的任一台 Broker,就能拿到整个集群的 Broker 信息,故没必要为 bootstrap.servers 指定所有的 Broker。

如果 bootstrap.servers 参数指定了 1000 个 Broker 连接信息,那么,Producer 启动时会首先创建与这 1000 个 Broker 的 TCP 连接。

TCP 连接还可能在两个地方被创建:一个是在更新元数据后,另一个是在消息发送时。 为什么说是可能?因为这两个地方并非总是创建 TCP 连接。当 Producer 更新了集群的元数据信息之后,如果发现与某些 Broker 当前没有连接,那么它就会创建一个 TCP 连接。同样地,当要发送消息时,Producer 发现尚不存在与目标 Broker 的连接,也会创建一个。

Producer 更新集群元数据信息的两个场景:

  • 场景一:当 Producer 尝试给一个不存在的主题发送消息时,Broker 会告诉 Producer 说这个主题不存在。此时 Producer 会发送 METADATA 请求给 Kafka 集群,去尝试获取最新的元数据信息。
  • 场景二:Producer 通过 metadata.max.age.ms 参数定期地去更新元数据信息。该参数的默认值是 300000,即 5 分钟,也就是说不管集群那边是否有变化,Producer 每 5 分钟都会强制刷新一次元数据以保证它是最及时的数据。
何时关闭 TCP 连接?

Producer 端关闭 TCP 连接的方式有两种:一种是用户主动关闭;一种是 Kafka 自动关闭

第一种的用户主动关闭实际上是广义的主动关闭,甚至包括用户调用 kill -9 主动“杀掉” Producer 应用。当然最推荐的方式还是调用 producer.close() 方法来关闭。

第二种是 Kafka 自动关闭,这与 Producer 端参数 connections.max.idle.ms 的值有关。默认情况下该参数值是 9 分钟,即如果在 9 分钟内没有任何请求“流过”某个 TCP 连接,那么 Kafka 会主动把该 TCP 连接关闭。用户在 Producer 端设置 connections.max.idle.ms=-1 会禁掉这种机制,TCP 连接将成为永久长连接。当然这只是软件层面的“长连接”机制,由于 Kafka 创建的这些 Socket 连接都开启了 keepalive,因此 keepalive 探活机制还是会遵守的。

在第二种方式中,TCP 连接是在 Broker 端被关闭的,但其实这个 TCP 连接的发起方是客户端,因此在 TCP 看来,这属于被动关闭的场景,即 passive close。被动关闭的后果就是会产生大量的 CLOSE_WAIT 连接,因此 Producer 端或 Client 端没有机会显式地观测到此连接已被中断。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

久违の欢喜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值