Kafka从2.5.1升级至3.2.0后消息发送显示成功但队列无数据且出现节点连接失败警告的问题排查请求
Kafka 3.2.0升级后消息假成功+连接警告问题分析
嘿,我之前升级Kafka版本时也踩过类似的坑,结合你的描述,问题主要出在异步发送的错误判断逻辑和新版本的连接/配置兼容性上,咱们一步步拆解:
1. 为什么会出现"发送成功"的假提示?
你现在用kafkaResponse.isDone()来判断消息是否发送成功,这是完全错误的——isDone()只表示异步操作已经完成,但这个完成可能是失败的(比如连接不上broker、发送超时),并不是真的发送成功。
Kafka生产者的send()是异步非阻塞的,返回的Future只有在调用get()方法时才会抛出异常,或者通过回调才能知道真实的发送结果。你现在的代码既没调用get(),也没加回调,完全没捕获到发送失败的异常,才会误以为消息发送成功。
2. 连接node-1的警告意味着什么?
Connection to node -1 could not be established这个警告是关键:node-1是Kafka生产者在获取broker元数据前临时用的节点ID,出现这个警告说明你的生产者根本连不上任何bootstrap服务器,自然无法把消息发送到topic。
之所以在2.5.1版本正常,大概率是3.2.0版本的broker配置或网络环境和旧版本有差异,比如:
- bootstrap.servers配置错误,和broker的listeners地址不匹配
- 新版本broker启用了SSL/SASL安全认证,而生产者没配置对应的参数
- 防火墙/网络策略阻止了生产者访问broker端口
- broker服务本身没正常启动,或者元数据同步有问题
3. 解决方案
先修复错误的发送结果判断逻辑
把你的代码改成下面两种方式之一,才能真正获取发送结果:
方式一:使用回调函数(推荐,非阻塞)
final ProducerRecord<String, String> producerRecord = new ProducerRecord<>("my_topic", this.toString()); producer.send(producerRecord, (metadata, exception) -> { if (exception != null) { System.err.println("消息发送失败:" + exception.getMessage()); // 这里可以添加重试或告警逻辑 } else { System.out.printf("消息成功发送到topic:%s,分区:%d%n", metadata.topic(), metadata.partition()); } }); // 确保消息被flush到broker producer.flush();
方式二:调用Future.get()(阻塞式,适合同步场景)
final ProducerRecord<String, String> producerRecord = new ProducerRecord<>("my_topic", this.toString()); Future<RecordMetadata> kafkaResponse = producer.send(producerRecord); try { RecordMetadata metadata = kafkaResponse.get(); System.out.printf("消息成功发送到topic:%s%n", metadata.topic()); } catch (InterruptedException | ExecutionException e) { System.err.println("消息发送失败:" + e.getMessage()); e.printStackTrace(); } producer.flush();
排查broker连接问题
- 检查
bootstrap.servers配置:确保和3.2.0 broker的listeners配置完全一致,比如broker配置的是PLAINTEXT://192.168.1.100:9092,生产者就不能写localhost:9092 - 验证网络连通性:用
telnet或nc命令测试生产者机器到broker端口的连通性,比如nc -zv 192.168.1.100 9092 - 检查broker状态:用Kafka自带的命令行工具查看broker是否正常运行,比如
kafka-topics.sh --list --bootstrap-server <broker地址>,同时确认my_topic存在且状态正常 - 核对安全配置:如果3.x broker开启了SSL或SASL,生产者需要添加对应的配置,比如
security.protocol=SSL、ssl.truststore.location等参数
其他注意事项
- 升级后确保生产者配置和新版本兼容:比如3.2.0的
delivery.timeout.ms默认值是120000ms,和2.5.1可能不同,若有特殊需求需要手动配置 - 程序结束前务必调用
producer.close():这个方法会自动flush所有缓存的消息,避免因程序退出导致消息丢失
内容的提问来源于stack exchange,提问作者Black




