阿里云kafka消息写入topic失败

1. 问题现象描述

20240918,14:22,测试反馈说kafka有问题,生产者写入消息的时候报错,并发了一张日志截图,主要报错如下:
to topic xxxx: org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for xxxx-0:120000 ms has passed since batch creation。

The cloud topic xxxx-0 dose not support idempotent and transaction, please use the local topic

第一条报错的大概意思是写入超时,也就是网络有问题。第二条报错是说topic不支持幂等和事务,请使用本地topic。

2. 排查过程

2.1 检查网络环境

这个kafka实例是用的阿里云的,服务和配置我都检查过,一个多月没改动了,但还是根据报错检查一下,我先自行在pod中telnet了一下kafka实例的地址,检查了白名单,随后又按照阿里云官方提供的检查方式,检查了网络、生产、消费等方面,都显示正常。

2.2 检查kafka topic存储类型

阿里云上的kafka,创建topic时,可选的存储是云存储和local存储,我这边所有的topic默认都是使用的云存储,但是根据云厂商的回复,客户端版本如果使用3.0及以上的话,是没有办法使用幂等的,就会导致消息发送失败,刚好我问了一下开发,说用的是3.7.1,但开发说已经关闭了幂等功能。
好吧,到这里排查不下去了,准备抓包。

2.3 测试写入其他topic

这里让开发改了一下代码,看看写入其他topic是否正常,测试结果没问题,写其他topic能写。

2.4 抓包

这里把版本回滚到了消息写入异常的这一版,pod中用tcpdump 抓和kafka通信的包,让开发手动触发消息写入,报文截图如下:
在这里插入图片描述
可以看到上面kafka客户端版本是3.7.0,我寻思这跟开发说的一不一样的,于是把版本发到能够正常写入消息的这一版,继续抓包,报文如下:
在这里插入图片描述
新发现,能写的这个客户端是3.7.1,随后反馈给开发。

3. 问题原因

最后跟开发沟通,是因为他在3.7.1这个客户端版本,关闭了使用幂等功能,所以消息能写了,其实不换客户端版本也没关系。
最后问开发老版本3.7.0是不是没关使用幂等,开发说不记得了,我服了!

### 数据传输长度限制及其解决方案 对于向阿里云发送数据时由于数据长度过长而导致接收失败的情况,通常是因为超过了API接口设定的最大请求体尺寸。针对此问题有几种常见处理方法[^1]。 #### 减少单次上传的数据量 如果应用程序允许的话,可以调整业务逻辑使得每次提交给服务器的信息变短。例如分批次读取本地文件内容再逐段上载;或者先做初步过滤只保留必要的字段值后再打包成JSON字符串等形式减少冗余度。 #### 使用流式传输方式 采用支持断点续传特性的SDK库函数实现大文件或多条记录的同时写入操作。这种方式下客户端能够持续不断地把新产生的二进制字节流传送给远程主机直到全部完成为止,并且在网络不稳定的情况下也可以自动重试未成功的部分而不必重新开始整个过程[^3]。 #### 利用消息队列中间件间接传递超限参数 创建一个临时的消息实体存放在RabbitMQ/Kafka这样的第三方组件内,之后仅需告知目标端点去对应的Topic/Queue里面拉取消息即可。这样做不仅解决了直接POST带来的体积约束难题,还增加了系统的解耦性和可扩展性。 ```python import json from aliyunsdkcore.client import AcsClient from aliyunsdkiot.request.v20180120.PublishMessageRequest import PublishMessageRequest def publish_large_data(client, topic, payload): request = PublishMessageRequest() request.set_accept_format('json') # 将大数据分割为多个较小的部分 chunk_size = 1024 * 1024 # 假设每块最大不超过1MB chunks = [payload[i:i + chunk_size] for i in range(0, len(payload), chunk_size)] message_id = None for index, chunk in enumerate(chunks): msg_info = { 'topic': f"{topic}/part/{index}", 'content': chunk.decode() if isinstance(chunk, bytes) else str(chunk), 'messageId': '' if not message_id else message_id, } body = json.dumps(msg_info).encode('utf-8') request.set_content(body) response = client.do_action_with_exception(request) result = json.loads(response) if 'success' in result and result['success']: message_id = result.get('data', {}).get('messageId') # 创建AcsClient实例并调用publish_large_data函数 client = AcsClient('<your-access-key-id>', '<your-access-secret>', 'cn-hangzhou') publish_large_data(client, '/path/to/topic', b'very large binary data...') ``` 上述代码展示了如何利用Python SDK将较大的二进制数据拆分成若干个小片段并通过指定的主题发布到阿里云IoT平台上,在实际开发过程中可根据具体需求灵活修改相应参数设置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值