温馨提示×

centos上kafka故障排查方法

小樊
31
2025-12-17 14:42:14
栏目: 智能运维

CentOS 上 Kafka 故障排查手册

一 快速定位流程

  • 查看服务状态与最近日志
    • systemd:执行 systemctl status kafka -l 或 journalctl -u kafka -f 实时跟踪
    • 包安装常见日志目录:/var/log/kafka/server.log;源码安装常见目录:KAFKA_HOME/logs/server.log
  • 确认依赖与网络
    • 确认 Zookeeper 已启动且可连接(如使用 systemd:systemctl status zookeeper)
    • 检查监听端口(默认 9092)是否被占用:ss -lntp | grep 9092 或 netstat -tulpen | grep 9092
    • 排查防火墙/安全组:firewall-cmd --list-ports;必要时放通 9092/tcp
  • 前台启动获取完整堆栈
    • 前台运行:/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties(便于直接看到异常栈)
  • 校验关键配置
    • server.properties 中的 broker.id(集群内唯一)、log.dirs(目录存在且权限正确)、zookeeper.connectlisteners/advertised.listeners 是否指向可达地址

二 常见故障与修复要点

  • 启动失败并提示 Failed to start Kafka Server
    • 检查 Zookeeper 是否运行与连接串是否正确(zookeeper.connect)
    • 校验 log.dirs 是否存在且属主/权限正确(例:mkdir -p /data/kafka/logs && chown -R kafka:kafka /data/kafka)
    • 检查 9092 端口是否被占用并调整 listeners 端口
    • 查看 server.log 具体报错定位根因
  • 启动即退出或报 Cannot allocate memory
    • 机器内存不足或 JVM 堆设置过大:调小 KAFKA_HEAP_OPTS(如 -Xms2G -Xmx2G),释放内存后重启
  • 无法连接 Broker(Connection to node -1 失败、超时)
    • 核对 listeners/advertised.listeners 是否使用客户端可达的 IP/域名
    • 在 /etc/hosts 为 broker 主机名添加解析(如 192.168.1.10 node1),避免 UnknownHostException
    • 排查防火墙/SELinux 与网络连通性(telnet/curl 到 9092)
  • 消费者 Rebalance 失败
    • 常见因成员无有效 member.id、网络抖动、配置错误;检查 group.idclient.id 一致性与版本兼容性,必要时重启消费者
  • 消息积压与性能问题
    • 可能由生产者过快、消费者处理能力不足、分区不均、网络延迟引起;优化消费逻辑、增加分区/消费者、启用压缩(compression.type)

三 配置与系统检查清单

  • 关键配置
    • 唯一 broker.id、正确的 zookeeper.connect
    • listeners/advertised.listeners 使用可被客户端解析的地址(建议 IP 或稳定 DNS)
    • log.dirs 所在磁盘空间充足、权限正确(属主 kafka:kafka)
    • 版本兼容:Broker 与客户端版本差异过大可能导致 API/行为不一致
  • 系统与资源
    • 文件句柄与进程数:/etc/security/limits.conf 设置 * soft/hard nofile 65536、nproc 65536,ulimit -a 验证
    • 内存与 GC:合理设置 KAFKA_HEAP_OPTS;必要时使用 G1GC 并调整 DirectMemory
    • 磁盘空间:监控并清理过期数据或扩容,避免因磁盘满导致异常

四 日志与监控

  • 日志查看与轮转
    • 实时查看:tail -f /opt/kafka/logs/server.log 或 journalctl -u kafka -f
    • 系统日志接入:rsyslog 配置 imfile 将 server.log 写入 /var/log/kafka/kafka.log
    • 轮转示例(/etc/logrotate.d/kafka):/opt/kafka/logs/*.log { daily rotate 7 missingok compress copytruncate }
  • 指标与告警
    • 部署 Kafka Exporter + Prometheus + Grafana 监控吞吐、请求耗时、错误率等,设置阈值告警

五 一键排查脚本示例

  • 用途:快速检查端口、进程、Zookeeper、关键配置与日志错误
  • 保存为 check_kafka.sh 并执行:bash check_kafka.sh
#!/usr/bin/env bash
set -Eeuo pipefail

KAFKA_HOME=${KAFKA_HOME:-/opt/kafka}
KAFKA_CONF=$KAFKA_HOME/config/server.properties
LOG_DIR=$(grep '^log\.dirs=' "$KAFKA_CONF" 2>/dev/null | cut -d'=' -f2- | tr -d '[:space:]')
ZK_CONN=$(grep '^zookeeper\.connect=' "$KAFKA_CONF" 2>/dev/null | cut -d'=' -f2- | tr -d '[:space:]')
LISTENERS=$(grep '^listeners=' "$KAFKA_CONF" 2>/dev/null | cut -d'=' -f2- | tr -d '[:space:]')
ADV_LISTENERS=$(grep '^advertised\.listeners=' "$KAFKA_CONF" 2>/dev/null | cut -d'=' -f2- | tr -d '[:space:]')
PORT=${LISTENERS##*:}

echo "=== Kafka 快速健康检查 ==="
echo "时间: $(date '+%F %T')"
echo

echo "[1/7] 端口 $PORT 占用情况"
ss -lntp | grep -E "(:$PORT|\*$PORT)" || echo "端口 $PORT 未被监听"

echo
echo "[2/7] Kafka 进程"
pgrep -x java | xargs -r ps -fp || echo "未检测到 Kafka Java 进程"

echo
echo "[3/7] Zookeeper 连通性"
if command -v nc >/dev/null 2>&1; then
  timeout 3 nc -z "${ZK_CONN%:*}" "${ZK_CONN##*:}" && echo "Zookeeper $ZK_CONN 可达" || echo "Zookeeper $ZK_CONN 不可达"
else
  echo "nc 未安装,跳过 Zookeeper 端口探测"
fi

echo
echo "[4/7] 关键配置"
echo "broker.id: $(grep '^broker\.id=' "$KAFKA_CONF" 2>/dev/null | cut -d'=' -f2-)"
echo "log.dirs: $LOG_DIR"
echo "zookeeper.connect: $ZK_CONN"
echo "listeners: $LISTENERS"
echo "advertised.listeners: $ADV_LISTENERS"

echo
echo "[5/7] 目录与权限"
if [[ -n "$LOG_DIR" ]]; then
  if [[ -d "$LOG_DIR" ]]; then
    echo "目录 $LOG_DIR 存在,权限: $(stat -c '%A %U:%G' "$LOG_DIR")"
  else
    echo "目录 $LOG_DIR 不存在"
  fi
else
  echo "未配置 log.dirs"
fi

echo
echo "[6/7] 防火墙状态"
if command -v firewall-cmd >/dev/null 2>&1; then
  firewall-cmd --list-ports | grep -qE "${PORT}/tcp" && echo "防火墙已放行 $PORT/tcp" || echo "防火墙未放行 $PORT/tcp"
else
  echo "firewalld 未安装"
fi

echo
echo "[7/7] 最近错误日志 (server.log)"
if [[ -f "$KAFKA_HOME/logs/server.log" ]]; then
  tail -n50 "$KAFKA_HOME/logs/server.log" | grep -i -E 'ERROR|Exception' | tail -20 || echo "最近 50 行中未检索到 ERROR/Exception"
elif [[ -f "/var/log/kafka/server.log" ]]; then
  tail -n50 "/var/log/kafka/server.log" | grep -i -E 'ERROR|Exception' | tail -20 || echo "最近 50 行中未检索到 ERROR/Exception"
else
  echo "未找到 server.log"
fi

提示:将脚本中的 KAFKA_HOME 与实际安装路径保持一致;若使用 systemd 管理服务,可先执行 systemctl status kafka 获取更详细的启动失败原因。

0