Kafka Expiring 172 record(s) for [topic_name]: 120000 ms has passed -> 生产者消息超时深度解析与解决方案

V1.0

从截图中可以看到 Kafka 的生产者日志显示了以下关键错误信息:

错误信息

Kafka error sending message: Expiring 172 record(s) for [topic_name]: 120000 ms has passed since batch creation.

分析

  1. 消息过期

    • 生产者在发送消息时,超过了配置的 delivery.timeout.ms 设置(默认为 120000 毫秒,或 2 分钟)。
    • 这意味着消息的发送时间(包括重试的时间)已经超过了允许的最大值,因此这些消息被丢弃。
  2. 可能的原因

    • 网络延迟或不稳定
      • Kafka 集群与生产者之间的网络延迟较高,导致消息无法及时送达。
    • Kafka 集群负载过高
      • Broker 处理请求的速度慢,无法及时写入日志文件。
    • 配置问题
      • delivery.timeout.ms 配置过低,无法容忍当前的网络和集群延迟。
    • 分区不可用或ISR过少
      • 如果分区的ISR(In-Sync Replica)数量不足,可能会导致写入请求被阻塞。
  3. 涉及的参数

    • delivery.timeout.ms:消息的最大允许发送时间。
    • linger.ms:批次创建后,生产者等待的最大时间。
    • batch.size:批次大小,超过批次限制会强制发送。
    • acks:生产者需要等待多少副本确认消息的写入。

解决方法

  1. 检查 Kafka 集群

    • 查看 Kafka Broker 日志,确认是否存在网络、磁盘或ISR不足的问题。
    • 确保 Kafka 集群负载正常。
  2. 优化生产者配置

    • 增加 delivery.timeout.ms 的值,例如调整为 300000 毫秒(5 分钟)。
    • 减小 batch.sizelinger.ms 的值,以减少批次的等待时间。
    • 修改 acks1(仅等待 leader 确认)以降低延迟(但会降低可靠性)。
  3. 监控网络

    • 确保生产者与 Kafka 集群之间的网络正常,没有明显的延迟或丢包。
  4. 测试集群性能

    • 使用工具(如 kafka-producer-perf-test.sh)测试 Kafka 的写入性能,排除生产者本身的问题。

V2.0 -> Kafka 生产者消息超时深度解析与解决方案

一、错误本质与核心机制

消息生命周期图解

Producer Buffer SenderThread Broker 创建消息批次 等待发送条件 发送请求 响应ACK 清除已发送批次 120s未收到ACK 报告"Expiring records" 丢弃消息批次 alt [超时场景] Producer Buffer SenderThread Broker

关键参数关系

linger.ms
批次创建
request.timeout.ms
单次请求超时
retries
重试次数
delivery.timeout.ms
总超时控制
发送频率
网络容错
故障恢复
消息可靠性

二、根本原因深度诊断

1. 网络问题排查矩阵

检测工具关键指标诊断阈值解决方案
ping延迟时间>100ms优化路由/切换线路
mtr丢包率>1%联系ISP提供商
tcpdumpTCP重传>5%调整内核参数
iperf带宽利用率>80%增加带宽/QoS

2. Kafka集群健康检查清单

# 检查Controller状态
bin/zookeeper-shell.sh localhost:2181 get /controller

# 检查ISR状态
bin/kafka-topics.sh --describe --bootstrap-server localhost:9092 | grep -E "Isr|Leader"

# 检查磁盘IO
iostat -x -d 1

# 检查请求队列
bin/kafka-configs.sh --bootstrap-server localhost:9092 --entity-type brokers --describe | grep queued.max

三、生产者配置优化指南

配置黄金法则

# 可靠性优先场景(金融交易)
delivery.timeout.ms=300000  # 5分钟
request.timeout.ms=30000    # 30秒
retries=2147483647          # Integer.MAX_VALUE
max.in.flight.requests.per.connection=1
acks=all
compression.type=none

# 吞吐量优先场景(日志收集)
delivery.timeout.ms=120000  # 2分钟
request.timeout.ms=20000    # 20秒
retries=5
max.in.flight.requests.per.connection=5
acks=1
compression.type=lz4

参数计算公式

最大允许重试时间

MaxRetryTime = retries * (request.timeout.ms + latency)

配置安全边界

delivery.timeout.ms > linger.ms + MaxRetryTime + 30s

四、集群端性能优化

Broker关键参数

# 网络线程优化
num.network.threads = 16
queued.max.requests = 2000

# 磁盘IO优化
num.io.threads = 32
log.flush.interval.messages=10000
log.flush.interval.ms=1000

# 副本管理
min.insync.replicas=2
unclean.leader.election.enable=false

ISR问题修复流程

副本滞后
Broker宕机
ISR不足
原因分析
检查副本同步
检查节点状态
优化复制参数
重启或替换节点
调整 replica.lag.time.max.ms
恢复副本数
验证ISR状态

五、高级监控与诊断

Prometheus监控指标

# 关键生产者指标
- kafka_producer_record_error_rate
- kafka_producer_request_latency_max
- kafka_producer_record_retry_rate
- kafka_producer_record_queue_time_avg

# Broker关键指标
- kafka_network_request_queue_size
- kafka_log_flush_time_max
- kafka_server_replica_manager_under_replicated

日志分析模式

ERROR Expiring 172 record(s) for orders-3: 
  BatchCreatedTime: 2023-06-15T10:30:00Z
  FirstAttemptTime: 2023-06-15T10:30:00Z
  LastAttemptTime: 2023-06-15T10:32:00Z
  RetryCount: 3
  LastBroker: broker-2:9092 (ID: 2)

诊断线索

  1. 重试次数 > 0:网络或Broker问题
  2. 固定Broker失败:节点特定问题
  3. 无重试:立即被拒绝

六、压力测试与验证

生产环境压测方案

# 基准测试
bin/kafka-producer-perf-test.sh \
  --topic TEST_TOPIC \
  --num-records 1000000 \
  --record-size 1024 \
  --throughput 10000 \
  --producer-props \
    bootstrap.servers=broker:9092 \
    acks=all \
    delivery.timeout.ms=120000

# 故障注入测试
tc qdisc add dev eth0 root netem \
  delay 500ms 100ms 25% \
  loss 5% 30% \
  duplicate 1%

性能指标解读

指标健康范围危险阈值优化方向
请求延迟<100ms>500ms网络/Broker优化
错误率<0.1%>5%参数调整/扩容
队列时间<50ms>200ms增加处理线程
重试率<1%>20%检查集群健康

七、灾备与高可用方案

多集群容灾架构

主路径
备路径
生产者
主Kafka集群
备份Kafka集群
主处理系统
灾备处理系统
业务数据库

客户端容错实现

// 双集群生产者示例
class FailoverProducer {
    private KafkaProducer<String, String> primary;
    private KafkaProducer<String, String> secondary;
    
    void send(String topic, String message) {
        try {
            primary.send(new ProducerRecord<>(topic, message), 
                (metadata, exception) -> {
                    if (exception != null) {
                        secondary.send(new ProducerRecord<>(topic, message));
                    }
                });
        } catch (Exception e) {
            secondary.send(new ProducerRecord<>(topic, message));
        }
    }
}

八、典型故障案例库

案例1:云服务跨区延迟

现象

  • 新加坡到美西集群延迟200ms+
  • 频繁出现120s超时

解决方案

  1. 部署区域代理集群
  2. 启用消息压缩(snappy)
  3. 调整参数:
    delivery.timeout.ms=300000
    request.timeout.ms=60000
    

案例2:磁盘IO瓶颈

现象

  • Broker磁盘util 100%
  • 生产者超时率 >15%

解决方案

  1. 升级SSD磁盘
  2. 优化日志保留策略
  3. 调整刷盘参数:
    log.flush.interval.messages=50000
    log.flush.scheduler.interval.ms=3000
    

终极建议:对于关键业务系统,始终设置 delivery.timeout.ms > linger.ms + retries * request.timeout.ms + 安全余量(30s),并实施端到端监控!

通过本方案,您不仅能解决当前的超时问题,更能构建高可靠的Kafka生产体系。当超时发生时,记得优先检查Broker健康状况和网络质量,它们贡献了90%的故障场景!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值