【exception】Java和kafka连接正常但是发送数据失败

描述

今天Java程序和kafka整合的时候遇到一个情况,Java可以和kafka连接但是在发送数据的时候出现了以下的异常:

-2019-07-30 14:55:08.494 -ERROR 2191 [kafka-producer-network-thread | producer-1] (LoggingProducerListener.java:84) Exception thrown when sending a message with key='null' and payload='[{"index_level":"1","unit":"%","id...' to topic testData:
-
org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for testData-0: 30032 ms has passed since batch creation plus linger time

看到连接超时一开始以为是连接的问题,但是连接是正常的,在寻找资料后,找到了一个解决这个问题的方法。

解决

启动zookeeper的客户工具,删除zookeeper根目录下的brokers目录下的topic目录下的所有东西(这样会把之前建的所有topic都删除)

具体步骤:

  1. 启动zookeeper 客户端:进到zookeeper的安装目录
[root@Node1 bin]# cd /usr/apps/zookeeper/bin/
[root@Node1 bin]# ls
README.txt  zkCleanup.sh  zkCli.cmd  zkCli.sh  zkEnv.cmd  zkEnv.sh  zkServer.cmd  zkServer.sh  zookeeper.out
  1. 运行zkCli.sh
[root@Node1 bin]# ./zkCli.sh 
Connecting to localhost:2181
  1. 查看/brokers/topic下面有什么东西
[zk: localhost:2181(CONNECTED) 0] ls /brokers/topics
  1. 删除里面所有的文件
[zk: localhost:2181(CONNECTED) 0]rmr /brokers/topics/hive-test-table
  1. 重新启动producer和consumer,Java重新发送就可以看发过来的数据

原因分析

具体原因不清楚。

但是这个超时是因为producer.properties配置文件有一个值是request.timeout.ms,默认是30秒。producer往broker发送数据时是串行的,只有上次batch全部写入broker,并且全部callback函数执行完毕后,才会继续下一次发送。如果上一次发送全部callback函数执行时间超过了30秒,就会导致后续batch的message发送时间大于创建时间30秒以上,然后被producer丢弃并抛出异常。

<think>嗯,我现在要了解Kafka生产者服务器是怎么发送数据的。首先,Kafka是一个分布式的流处理平台,生产者负责把数据发送到Kafka集群里的主题(topic)里。但是具体步骤是怎样的呢?可能需要从生产者创建开始,然后配置参数,接着发送数据,最后处理确认消息。 首先,生产者需要配置一些必要的参数,比如bootstrap.servers,这个是Kafka集群的地址列表,对吧?然后可能需要指定keyvalue的序列化方式,比如StringSerializer。接下来,生产者会创建一个ProducerRecord,里面包含要发送的主题、键。这时候,生产者会把这个记录发送出去,但发送的过程是怎样的呢? 可能涉及到分区选择。如果指定了分区,就直接发到那个分区;如果没有,但指定了key,就会根据key的哈希选择一个分区;如果都没指定,可能用轮询的方式分配分区。然后数据会被放到一个缓冲区里,可能积累到一定大小或者时间后批量发送。这时候生产者可能异步发送,需要等待服务器的确认,但也可以同步发送,等确认返回。 还有可能涉及到acks配置,比如0表示等待确认,1表示等待leader确认,all表示所有副本都确认。这会影响数据的可靠性吞吐量之间的平衡。另外,重试机制,如果发送失败的话,生产者会自动重试,但可能会有重复消息的风险,需要幂等性配置来避免。 此外,生产者可能使用批处理来提高效率,通过linger.ms参数控制等待时间,使得多个记录可以一起发送,减少网络开销。还有压缩选项,可以压缩数据,节省带宽。 在代码层面,可能需要用KafkaProducer的send方法,入ProducerRecord一个回调函数来处理发送成功或失败的情况。比如在Java中,可能是这样的结构: ProducerRecord<String, String> record = new ProducerRecord<>("topic", "key", "value"); producer.send(record, (metadata, exception) -> { if (exception != null) { // 处理异常 } else { // 处理成功 } }); 然后需要关闭生产者,释放资源。可能还要处理可能的错误,比如序列化错误、网络错误、缓冲区满等异常情况。 过,用户的问题是要介绍发送数据的过程,可能需要更系统化的步骤说明,包括创建生产者、配置参数、序列化、分区选择、批次处理、发送方式(同步/异步)、确认机制、错误处理等。需要把这些步骤整理清楚,用中文解释清楚每个环节的作用配置方式,同时注意使用正确的LaTeX格式。</think>Kafka生产者服务器发送数据的过程可分为以下步骤,结合关键配置内部机制详细说明: --- ### 1. **生产者初始化** 创建生产者实例时需配置核心参数: ```java Properties props = new Properties(); props.put("bootstrap.servers", "kafka1:9092,kafka2:9092"); // 集群地址 props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); props.put("acks", "all"); // 数据可靠性配置 props.put("retries", 3); // 重试次数 props.put("linger.ms", 5); // 批次等待时间 KafkaProducer<String, String> producer = new KafkaProducer<>(props); ``` --- ### 2. **构造消息** 消息封装为`ProducerRecord`对象,包含: - **Topic**:目标主题 - **Partition**(可选):指定分区 - **Key**(可选):用于分区路由 - **Value**:消息内容 例如: $$ \text{ProducerRecord} = (\text{topic}, \text{key}, \text{value}) $$ --- ### 3. **分区路由策略** 生产者根据规则选择目标分区: - **显式指定分区**:直接发送到指定分区 - **Key哈希**:未指定分区时,按Key哈希选择分区(相同Key入同一分区) - **轮询策略**:无Key时,轮询分配同分区 --- ### 4. **数据批处理与压缩** - **批次积累**:消息先存入缓冲区(`RecordAccumulator`),达到`batch.size`或`linger.ms`阈后批量发送 - **压缩算法**:通过`compression.type`配置(如gzip、snappy),减少网络输量 --- ### 5. **网络发送** - **异步发送**:默认模式,通过`send()`方法非阻塞发送,配合回调处理结果: ```java producer.send(record, (metadata, e) -> { if (e != null) { // 处理失败逻辑 } else { // 成功时获取分区、偏移量等信息 } }); ``` - **同步发送**:调用`get()`方法阻塞等待结果: ```java producer.send(record).get(); ``` --- ### 6. **消息确认机制(acks)** - **`acks=0`**:等待Broker确认,可能丢失数据 - **`acks=1`**:仅Leader副本确认,保证Leader写入成功 - **`acks=all`**(或`-1`):需所有ISR副本确认,最高可靠性 --- ### 7. **错误处理与重试** - **网络异常**:自动重试(次数由`retries`控制) - **幂等性**:启用`enable.idempotence=true`避免重复消息(需Kafka 0.11+) - **事务支持**:跨分区原子写入(配置`transactional.id`) --- ### 8. **资源释放** 发送完成后关闭生产者,释放TCP连接缓冲区: ```java producer.close(); ``` --- ### 关键优化参数总结 | 参数 | 作用 | 示例 | |---------------------|--------------------------------|-------------| | `buffer.memory` | 缓冲区大小 | 33554432 (32MB) | | `max.block.ms` | 缓冲区满时阻塞时间 | 60000 | | `request.timeout.ms`| 等待Broker响应的超时时间 | 30000 | --- 通过上述流程,Kafka生产者在吞吐量、延迟可靠性之间实现平衡。实际应用中需根据场景调整参数,如高吞吐场景可增大批次压缩,强可靠场景需配置`acks=all`幂等性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值