某生產環境 Kafka Producer 通過公網 SSL 連接 Broker,消息發送成功但**建立連接耗時近 50 秒**。經多維度排查,最終定位為**客戶端無法反向解析 Broker IP 對應的主機名**,導致 DNS 超時阻塞。本文完整復盤現象、環境、排查鏈路、根因證據、解決方案與預防措施。
| 組件 | 網絡位置 | IP/端口 | 協議 |
| Kafka Broker | 數據中心內網 | 10.1.1.1:9092 (PLAINTEXT) 10.1.1.1:9093 (SSL) | 雙監聽 |
| 端口映射 | 防火牆/NAT | 公網 x.x.x.x:9093 → 10.1.1.1:9093 | 僅映射 SSL 端口 |
| Producer | 公網客戶端 | 連接 x.x.x.x:9093 | SSL |
Broker 關鍵配置
listeners=PLAINTEXT://0.0.0.0:9092,SSL://0.0.0.0:9093
advertised.listeners=PLAINTEXT://10.1.1.1:9092,SSL://x.x.x.x:9093
ssl.client.auth=required
Producer 關鍵配置
bootstrap.servers=x.x.x.x:9093
security.protocol=SSL
ssl.protocol=SSL
ssl.keystore.location=client.keystore.jks
ssl.truststore.location=client.truststore.jks
三、 排查鏈路復盤
1. tcpdump 抓包:SSL 握手正常,但 SYN 發送延遲 10+ 秒
# 抓取 9093 端口
tcpdump -i eth0 -nn port 9093 -w kafka.pcap
# 分析發現:
# 1. Producer 啟動後 ~10s 才發送第一個 SYN
# 2. SSL Client Hello → Server Hello → Certificate → Finished 正常完成
# 3. 應用層數據傳輸正常
# 結論:網絡連通性正常,延遲發生在 **發起 TCP 連接之前**
2. 全端口抓包:發現 137 端口 (NetBIOS) 名稱查詢
"main" #1 prio=5 os_prio=0 tid=0x... nid=0x... runnable
java.net.InetAddress.getHostByAddr(InetAddress.java:...)
java.net.InetAddress.getHostFromNameService(InetAddress.java:...)
sun.security.ssl.SSLSocketImpl.getPeerPrincipal(SSLSocketImpl.java:...)
org.apache.kafka.common.network.SslTransportLayer.handshake(SslTransportLayer.java:...)
org.apache.kafka.common.network.KafkaChannel.prepare(KafkaChannel.java:...)
org.apache.kafka.clients.NetworkClient.poll(NetworkClient.java:...)
org.apache.kafka.clients.producer.KafkaProducer.send(KafkaProducer.java:...)
四、 根因確鑿
- Producer 配置
bootstrap.servers=x.x.x.x:9093 使用 **IP 地址**
- SSL 握手階段,Kafka/JDK 內部調用
SSLSocketImpl.getPeerPrincipal() 校驗服務器證書
- 證書 CN/SAN 為 **主機名**(如
kafka-broker-1),需將連接的 IP 反向解析為主機名進行比對
- JDK 調用
InetAddress.getHostByAddr(ip) 觸發 DNS PTR 反向查詢
- 公網 DNS 無該 IP 的 PTR 記錄,查詢超時(NetBIOS 兜底再超時)
- 阻塞 ~50 秒後解析失敗,但 SSL 握手**繼續執行**(未強制要求主機名驗證通過),最終連接建立
五、 解決方案驗證
方案一:Producer 端配置 hosts 文件(最快生效)
# /etc/hosts (Linux) 或 C:\Windows\System32\drivers\etc\hosts (Windows)
x.x.x.x kafka-broker-1 # IP 對應證書 CN/SAN 中的主機名
**效果**:連接建立從 50s 降至 <100ms,故障徹底解決。
方案二:DNS 服務器添加 PTR 記錄(標準運維)
// 自定義 HostnameVerifier 跳過驗證
ssl.endpoint.identification.algorithm= # 置空禁用 (Kafka 2.0+)
# 或
System.setProperty("jdk.tls.client.protocols", "TLSv1.2"); // 不解決根因
六、 深度思考:為什麼配置 IP 還要反向解析?
SSL/TLS 標準(RFC 6125)要求**驗證服務器身份**時,將連接的 IP 與證書中的 Subject Alternative Name (SAN) / Common Name (CN) 比對。當配置為 IP 時:
- 若證書 SAN 包含 IP 地址 → 直接比對,**無需 DNS**
- 若證書僅含主機名 → **必須將 IP 反向解析為主機名** 再比對
**最佳實踐**:生成 Broker 證書時,**在 SAN 中同時包含 IP 和主機名**:
- 上一篇文章: Linux perf 工具實戰:從采樣原理到火焰圖生成的性能分析全流程
- 下一篇文章: Go 常用命令全景速查:build、run、test、mod、vet、pprof 實戰參數詳解
Copyright ©
程式碼之家 All Rights Reserved