美文网首页
【kafka】kafka broker 节点主机名解析导致kaf

【kafka】kafka broker 节点主机名解析导致kaf

作者: Bogon | 来源:发表于2025-05-06 23:56 被阅读0次

3 节点的 kafka集群(依赖zookeeper):

192.168.31.183   
192.168.31.199   
192.168.31.178 

本机就是 192.168.31.178 ,在本机上执行,为什么会耗时这么长?!

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether fa:20:9a:77:32:00 brd ff:ff:ff:ff:ff:ff
    altname enp0s3
    inet 192.168.31.178/24 brd 192.168.31.255 scope global noprefixroute ens3


$ time /path/to/kafka/bin/kafka-topics.sh  --list  --zookeeper 192.168.31.178:2181

real    0m21.216s
user    0m1.467s
sys     0m0.281s

在本机执行 kafka-topics.sh --list --zookeeper 命令耗时长达21秒,远高于正常水平(通常应小于1秒)。

  • DNS解析延迟

尽管直接使用IP地址,但Kafka/ZooKeeper内部可能触发反向DNS查询(如日志记录或安全认证)。检查 /etc/hosts 是否配置本机IP与主机名映射,避免DNS阻塞 。

kafka集群明明是基于ip组件的集群。

在 kafka 3节点 /etc/hosts 下添加kafka集群3节点解析:

192.168.31.183   bogon-cache01
192.168.31.199   bogon-cache02
192.168.31.178   bogon-cache03
$ time /kingdee/kafka/bin/kafka-topics.sh --list --zookeeper 192.168.31.178:2181

real    0m1.233s
user    0m1.501s
sys     0m0.338s

问题就解决了 ,为什么?

在 Kafka 和 ZooKeeper 的架构中,即使集群节点间通过 IP 地址进行通信,某些组件或操作仍可能依赖 主机名解析(hostname resolution),尤其是在以下场景中:


关键原因分析

1. Kafka/ZooKeeper 内部对主机名的隐式依赖

  • ZooKeeper 的节点注册
    Kafka Brokers 在启动时会将自己的元数据(如地址、端口)写入 ZooKeeper 的 /brokers/ids 路径下。如果 Kafka 配置的 advertised.listeners(或旧版本的 advertised.host.name)设置为 主机名(而非 IP),ZooKeeper 中存储的节点信息会包含主机名。当执行 kafka-topics.sh --list 时,Kafka 会读取这些主机名并尝试解析为 IP,若 DNS 或 /etc/hosts 未正确配置,会导致解析阻塞。

  • Java 的网络库行为
    Kafka 和 ZooKeeper 基于 Java NIO 实现,某些网络操作(如 InetAddress.getCanonicalHostName())会自动触发反向 DNS 解析(Reverse DNS Lookup)。如果 /etc/hosts 中未预定义主机名与 IP 的映射,系统会尝试通过 DNS 查询,而 DNS 可能因网络问题或配置错误(如 DNS 服务器不可达)导致长时间等待。

2. Kafka Broker 的 advertised.listeners 配置问题

  • 如果 advertised.listeners 配置为主机名(例如 PLAINTEXT://bogon-cache03:9092),而 /etc/hosts 中未定义 bogon-cache03 的 IP 映射,其他组件(如 Kafka CLI 工具)在解析此地址时会触发 DNS 查询,导致延迟。
  • 即使 Kafka 集群实际通过 IP 通信,元数据操作(如 Topic 列表查询)仍可能涉及主机名解析。

3. ZooKeeper 的 Session 建立延迟

  • ZooKeeper 客户端(包括 Kafka CLI 工具)在建立连接时,会记录客户端的地址信息并可能触发主机名解析。如果解析缓慢,会拖慢整个会话初始化过程。

验证步骤

  1. 检查 Kafka 配置

    grep advertised.listeners /path/to/kafka/config/server.properties
    

    如果输出类似 PLAINTEXT://bogon-cache03:9092,则需确保 bogon-cache03 能被解析为 IP。

  2. 手动测试主机名解析

    # 清除本地 DNS 缓存(Linux)
    sudo systemd-resolve --flush-caches
    
    # 测试主机名解析
    time nslookup bogon-cache03
    

    如果解析耗时超过 1 秒,则表明系统依赖 DNS 且存在延迟。

  3. 检查 ZooKeeper 中存储的 Broker 元数据

    # 进入 ZooKeeper CLI
    zkCli.sh -server 192.168.31.178:2181
    
    # 查看 Broker 注册信息
    get /brokers/ids/0
    

    输出内容可能包含主机名(如 "host":"bogon-cache03"),此时 Kafka CLI 工具需解析该主机名。


解决方案的本质

将主机名与 IP 的映射写入 /etc/hosts 后,系统会优先从本地文件解析主机名,避免触发 DNS 查询,从而消除网络延迟。这是生产环境中常见的优化手段,尤其适用于以下情况:

  • DNS 服务器不可靠或响应缓慢。
  • Kafka/ZooKeeper 配置依赖主机名(如 advertised.listeners)。
  • 需要确保集群内部通信的确定性和高性能。

最佳实践建议

  1. 统一使用 IP 配置(推荐)
    在 Kafka 的 server.properties 中显式指定 advertised.listeners 为 IP 地址,避免依赖主机名:

    advertised.listeners=PLAINTEXT://192.168.31.178:9092
    
  2. 完善 /etc/hosts 配置
    在所有节点的 /etc/hosts 中定义集群节点的主机名与 IP 映射,确保本地解析快速可靠:

    192.168.31.178 bogon-cache03
    192.168.31.183 bogon-cache01
    192.168.31.199 bogon-cache02
    
  3. 禁用反向 DNS 解析(高级)
    修改 Kafka/ZooKeeper 的 JVM 参数,禁用 Java 的默认反向 DNS 解析:

    -Dsun.net.inetaddr.ttl=5  # 设置 DNS 缓存时间
    -Djava.net.preferIPv4Stack=true
    -Djava.net.preferIPv6Addresses=false
    

总结

尽管 Kafka 集群基于 IP 通信,但其元数据管理(通过 ZooKeeper)和部分网络操作仍可能依赖主机名解析。
若未正确配置 /etc/hosts 或 DNS,会导致 CLI 工具因解析延迟而卡顿。
通过本地绑定主机名与 IP,可彻底规避 DNS 查询的不确定性,显著提升操作效率。

如果不在 etc/hosts 手动写解析,注释掉 /etc/resolv.conf 也可以解决。为什么 ?

在 Kafka 集群中,若选择不手动配置 /etc/hosts,而是通过注释 /etc/resolv.conf 中的 DNS 配置来解决主机名解析延迟问题,其核心逻辑与 Linux 系统的解析机制和 Kafka 的依赖关系密切相关。以下是具体分析:


1. 系统解析流程的优先级:/etc/hosts 优先于 DNS

  • Linux 系统的名称解析由 /etc/nsswitch.conf 文件定义,默认的解析顺序为 files dns,即:
    1. 先查询 /etc/hosts 文件(静态映射)。
    2. 若未找到,则通过 /etc/resolv.conf 中的 DNS 服务器进行动态解析
  • 如果 /etc/hosts 未配置主机名与 IP 的映射,但 /etc/resolv.conf 被注释(即无可用 DNS 服务器),系统在遇到主机名解析请求时将直接失败,而非等待 DNS 超时。这避免了因 DNS 查询缓慢或不可达导致的延迟。

2. Kafka/ZooKeeper 的主机名依赖场景

  • 场景 1:advertised.listeners 配置为主机名
    若 Kafka Broker 的 advertised.listeners 设置为 PLAINTEXT://bogon-cache03:9092,其他组件(如 Kafka CLI 工具)在连接时需解析 bogon-cache03 的 IP。此时:
    • /etc/hosts 未配置 bogon-cache03,且 /etc/resolv.conf 被注释,则解析失败,可能导致 Kafka CLI 工具报错退出,而非等待 DNS 超时。
    • 但实际测试中,用户发现注释 resolv.conf 后命令成功执行,这表明 Kafka 可能通过其他方式规避了主机名依赖(见下文分析)。
  • 场景 2:ZooKeeper 存储的 Broker 元数据
    Kafka 将 Broker 信息(如地址)写入 ZooKeeper 的 /brokers/ids 路径。若配置不当,这些信息可能包含主机名。例如:
    # ZooKeeper 中存储的 Broker 元数据示例
    {"jmxPort":-1,"timestamp":"1620000000000","endpoints":["PLAINTEXT://bogon-cache03:9092"],"host":"bogon-cache03","port":9092}
    
    若 Kafka CLI 工具读取到此类元数据,则需解析 bogon-cache03。若 /etc/resolv.conf 被注释,解析失败可能导致工具崩溃,但实际测试未出现此现象,说明存在其他规避机制。

3. 注释 resolv.conf 的潜在效果

  • 效果 1:强制解析失败,而非等待超时
    /etc/resolv.conf 被注释时,系统无法发起 DNS 查询,直接返回解析错误(如 UnknownHostException)。Kafka CLI 工具可能对此类错误进行了快速处理,而非长时间阻塞。例如:
    • Kafka 客户端库(如 org.apache.kafka.common.utils.Utils)在解析失败时,可能直接回退到 IP 地址(若配置允许)或快速抛出异常,避免 DNS 超时。
  • 效果 2:Kafka 配置隐式规避主机名依赖
    若 Kafka 的 advertised.listenerslisteners 配置为 IP 地址(而非主机名),则 Broker 注册到 ZooKeeper 的元数据将直接使用 IP,避免主机名解析需求。此时即使 /etc/resolv.conf 被注释,也不会触发 DNS 请求。
  • 效果 3:系统解析库的回退行为
    某些 Linux 发行版的解析库(如 glibc)在 DNS 不可用时,可能尝试通过 gethostname()gethostbyname() 的本地缓存快速失败。若 Kafka CLI 工具未显式依赖主机名解析,则可能跳过 DNS 查询步骤。

4. 为何实际测试中问题被解决?

  • 可能性 1:Kafka 配置实际使用 IP 地址
    若 Kafka 的 advertised.listenerslisteners 均配置为 IP(如 PLAINTEXT://192.168.31.178:9092),则 ZooKeeper 中存储的 Broker 元数据将直接包含 IP 地址,无需解析主机名。此时即使 /etc/resolv.conf 被注释,CLI 工具仍可通过 IP 直接通信,问题自然消失。
  • 可能性 2:Kafka CLI 工具的容错机制
    Kafka CLI 工具(如 kafka-topics.sh)在连接 ZooKeeper 时,可能通过以下方式规避主机名解析:
    1. 直接使用命令行参数中的 IP 地址(如 --zookeeper 192.168.31.178:2181),而非依赖 ZooKeeper 中存储的主机名。
    2. 忽略 ZooKeeper 元数据中的主机名字段,直接通过 IP 与 Broker 通信。
  • 可能性 3:系统解析缓存的作用
    若此前已通过 /etc/hosts 解析过主机名,系统可能缓存了结果(如 nscdsystemd-resolved),即使后续注释 resolv.conf,缓存仍可提供快速响应。但用户描述中未提及缓存操作,此可能性较低。

5. 风险与注意事项

  • 风险 1:其他依赖 DNS 的服务失效
    注释 resolv.conf 会导致所有依赖 DNS 解析的服务(如 HTTP 请求、外部 API 调用)失败,可能引发连锁问题。
  • 风险 2:Kafka 功能受限
    若 Kafka 某些功能(如跨集群镜像、ACL 主机名匹配)依赖 DNS 解析,注释 resolv.conf 可能导致功能异常。
  • 最佳实践建议
    • 优先配置 /etc/hosts:显式定义集群节点的主机名与 IP 映射,确保本地解析快速可靠。
    • 避免注释 resolv.conf:若需优化解析性能,可通过以下方式:
      • 添加 options single-request-reopenresolv.conf,减少 DNS 请求延迟。
      • 使用本地 DNS 缓存工具(如 dnsmasq)。

总结

注释 /etc/resolv.conf 能解决 Kafka 命令延迟问题,本质是通过阻断 DNS 查询路径,避免因解析失败或超时导致的阻塞。但这一方法依赖 Kafka 的实际配置(如是否使用 IP 地址)和工具链的容错能力,存在较大风险,不建议作为长期方案。推荐优先完善 /etc/hosts 配置,并排查 Kafka 的主机名依赖场景,以实现更稳定的集群管理。

kafka 配置参数 advertised.listeners 解析

Kafka advertised.listeners 参数详解

advertised.listeners 是 Apache Kafka 中一个非常重要的配置参数,它决定了客户端如何连接到 Kafka 集群。下面我将详细解析这个参数的作用、配置方式,并通过多个示例说明其用法。

基本概念

advertised.listeners 参数用于指定 Kafka 代理(broker)向客户端公布的监听地址。当客户端连接到 Kafka 集群时,会从 broker 获取这个地址,然后使用该地址进行后续通信。

与 listeners 参数的区别

  • listeners: 指定 broker 实际绑定的网络接口和端口
  • advertised.listeners: 指定客户端应该使用的连接地址

这两个参数通常需要配合使用,特别是在复杂的网络环境中。

参数格式

advertised.listeners 的格式为:

协议://主机名或IP:端口

支持的协议包括:

  • PLAINTEXT (不加密)
  • SSL (SSL加密)
  • SASL_PLAINTEXT (SASL认证,不加密)
  • SASL_SSL (SASL认证,SSL加密)

典型配置示例

示例1:简单本地环境

listeners=PLAINTEXT://:9092
advertised.listeners=PLAINTEXT://localhost:9092

示例2:多协议配置

listeners=PLAINTEXT://:9092,SSL://:9093
advertised.listeners=PLAINTEXT://kafka.example.com:9092,SSL://kafka-secure.example.com:9093

示例3:Docker/Kubernetes 环境

listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://kafka-broker-1:9092

示例4:AWS EC2 环境

listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://ec2-12-34-56-78.compute-1.amazonaws.com:9092

高级场景

场景1:内外网分离

当 Kafka 集群部署在云环境中,内部服务和外部客户端需要不同的访问地址:

listeners=PLAINTEXT://0.0.0.0:9092,INTERNAL://0.0.0.0:19092
advertised.listeners=PLAINTEXT://public.example.com:9092,INTERNAL://kafka-internal:19092
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,INTERNAL:PLAINTEXT

场景2:Kubernetes StatefulSet

在 Kubernetes 中使用 StatefulSet 部署 Kafka:

listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://${HOSTNAME}.kafka-headless.default.svc.cluster.local:9092

常见问题解决

  1. 客户端连接问题:如果客户端无法连接,检查 advertised.listeners 是否配置了客户端可访问的地址

  2. DNS解析问题:确保 advertised.listeners 中的主机名可以被客户端解析

  3. 防火墙问题:确保 advertised.listeners 指定的端口在防火墙中是开放的

  4. 协议不匹配:确保客户端使用的协议与 advertised.listeners 中配置的协议一致

最佳实践

  1. 在生产环境中,总是明确配置 advertised.listeners
  2. 在云环境中,使用环境变量动态设置 advertised.listeners
  3. 对于容器化部署,考虑使用 headless 服务的 DNS 记录
  4. 定期测试从客户端网络到 advertised.listeners 的连接性

通过合理配置 advertised.listeners,可以确保 Kafka 集群在各种网络环境下都能被正确访问。

如何解读下面这段话?

kafka 中通过一个参数 advertised.listeners,来控制接收消息的ip和端口,同时这个地址也会注册到 zookeeper 中,当有请求连接到kafka时,如果和注册到zookeeper的kafka信息不匹配无法进行连接。

advertised.listeners 是 Kafka 中一个非常重要的配置参数,它决定了客户端和其他 Broker 如何连接到当前 Broker。
如果配置不正确,可能会导致客户端无法正常连接或通信失败。

下面详细总结其核心机制和关键注意事项:


1. advertised.listeners 的核心作用

  • 注册到 ZooKeeper
    Broker 启动时,会将 advertised.listeners 中定义的地址(IP:Port)注册到 ZooKeeper 的 /brokers/ids/<broker-id> 节点下,作为该 Broker 的公开访问地址。
  • 客户端连接导向
    客户端通过 bootstrap.servers 初始连接后,会从 ZooKeeper 或 Broker 元数据请求中获取 advertised.listeners 的地址。如果客户端无法访问该地址(如网络不通、地址解析失败),连接会失败。

2. 关键配置规则

(1) 必须与 listeners 配合使用

  • listeners:定义 Broker 实际绑定的网络接口和端口(即 Broker 监听的地址)。
    • 例如:listeners=PLAINTEXT://0.0.0.0:9092 表示监听所有网卡的 9092 端口。
  • advertised.listeners:定义客户端和其他 Broker 应该使用的地址
    • 若未显式配置,默认使用 listeners 的值。
    • 特殊场景:如果 listeners 包含 0.0.0.0(监听所有网卡),则必须显式配置 advertised.listeners,否则客户端可能拿到内网 IP 或 Docker 容器 IP,导致连接失败。

(2) 地址必须可被客户端访问

  • 如果 advertised.listeners 注册的是内网 IP(如 192.168.1.100:9092),但客户端在外网,则连接会失败。
  • 在云环境(如 AWS、K8s)中,通常需要配置公网 IP 或负载均衡器地址。

3. 典型配置场景

场景 1:本地开发(单机)

# Broker 监听本地回环地址
listeners=PLAINTEXT://127.0.0.1:9092
# 注册到 ZooKeeper 的地址(客户端直接连接)
advertised.listeners=PLAINTEXT://127.0.0.1:9092

场景 2:云服务器(公网访问)

# 监听内网 IP 和端口
listeners=PLAINTEXT://10.0.0.1:9092
# 注册公网 IP(客户端通过公网连接)
advertised.listeners=PLAINTEXT://54.32.10.5:9092

场景 3:Docker/K8s 环境

# 监听容器内所有网卡
listeners=PLAINTEXT://0.0.0.0:9092
# 注册宿主机映射的地址(需端口映射)
advertised.listeners=PLAINTEXT://host-machine-ip:31092

场景 4:内外网分离(多协议)

# 内网走 PLAINTEXT,外网走 SSL
listeners=INTERNAL://0.0.0.0:9092,EXTERNAL://0.0.0.0:9093
advertised.listeners=INTERNAL://192.168.1.100:9092,EXTERNAL://api.kafka.example.com:9093
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:SSL
inter.broker.listener.name=INTERNAL  # Broker 间通信使用内网

4. 常见问题与排查

问题 1:客户端连接超时或无法连接

  • 原因advertised.listeners 注册的地址不可达(如内网 IP 暴露给外网客户端)。
  • 解决:确保注册的地址能被客户端访问,必要时配置 NAT、负载均衡或域名。

问题 2:Broker 间通信失败

  • 原因inter.broker.listener.name 未正确指定,导致 Broker 间使用错误的地址通信。
  • 解决:显式配置 inter.broker.listener.name=INTERNAL(参考场景 4)。

问题 3:ZooKeeper 中的地址与实际不符

  • 排查
    1. 查看 ZooKeeper 注册信息:
      zookeeper-shell.sh localhost:2181 get /brokers/ids/<broker-id>
      
    2. 对比 advertised.listeners 配置是否一致。

5. 验证工具

  1. kafkacat 测试连接
    kafkacat -L -b <bootstrap-server>  # 查看 Broker 返回的元数据地址
    
  2. Telnet/Netcat 检查端口
    nc -vz <advertised-ip> <advertised-port>
    

总结

  • 核心原则advertised.listeners 必须注册客户端可访问的地址,且与 listeners 协同配置。
  • 复杂环境:在云、容器或多网卡场景中,需显式区分内外网地址,避免依赖默认值。
  • 验证步骤:通过 ZooKeeper 元数据和网络工具双重验证,确保地址一致性。

参考

Kafka超时异常全解析:从TimeoutException到集群配置优化
https://mp.weixin.qq.com/s/ZlaPBW3xTLwypgjZl4Dlkg

关于一个kafka无法正常连接问题的部署处理
https://mp.weixin.qq.com/s/bpm7WF-C4OlIvnIl7tC0CQ

kafka中的advertised.listeners你真的理解吗
https://mp.weixin.qq.com/s/OiAoqLqoegDF2i03z7eMcA

Kafka的数据可靠性保障与网卡隔离问题
https://mp.weixin.qq.com/s/ADTAJPZ7aJG8elj6GtbOkQ

Kafka系列之生产级集群参数配置
https://mp.weixin.qq.com/s/qzXiCB45zhYwv9yApyCvLA

相关文章

网友评论

      本文标题:【kafka】kafka broker 节点主机名解析导致kaf

      本文链接:https://www.haomeiwen.com/subject/drfjijtx.html