调试难以定位的RabbitMQ Frame Error问题
Minikube中RabbitMQ间歇性501 Frame Error问题
在Minikube环境运行RabbitMQ Server及Deno客户端应用做开发时,间歇性收到501 Frame Error,该错误在60条消息/秒、单条消息2-5KB的负载场景下频繁触发。
RabbitMQ日志错误信息
2023-02-26 16:43:12.635470+00:00 [error] <0.1056.0> operation none caused a connection exception frame_error: "type 3, first 16 octets = <<\"{\\\"payload\\\":{\\\"res\">>: {invalid_frame_end_marker, 99}" 2023-02-26 16:43:15.638860+00:00 [error] <0.1056.0> closing AMQP connection <0.1056.0> (10.244.0.18:60608 -> 10.244.0.21:5672): 2023-02-26 16:43:15.638860+00:00 [error] <0.1056.0> fatal_frame_error
客户端环境
使用deno-amqp库(v0.23.0)开发的Deno应用。
TCP抓包分析
Wireshark抓包显示服务器报错前的TCP段特征:
- 以0x63(十进制99,与错误信息中的标记一致)结尾;
- 包含内容帧末尾、publish方法、内容头(大小4428)、内容帧起始(头大小标注4428,但实际仅4384字节,缺失44字节);
- 起始内容帧以
{"payload": { "id"...开头,与错误信息中的"res"不匹配; - 缺失的44字节内容在服务器报告无效帧结束标记后才发送,恰好能填补之前内容帧的缺失部分。
客户端发送前帧验证
已确认AMQP客户端编码的帧格式无问题,验证代码如下:
if (data[7 + payload.byteLength] !== 206) { console.log('sending invalid frame end') console.log({ frame, data }); }
写入逻辑确认
尽管存在大量异步函数发布消息,已确保将所有连续帧(publish方法、头、消息体)分组,并通过writeAll完整写入缓冲区。已知Deno.Conn默认在写入时会停止事件循环,无并发TCP连接写入情况。
复现尝试
使用相同库向Docker RabbitMQ实例发送更大、更快的消息进行压力测试,未出现同类错误,仅在Minikube环境中能复现。
负载优化尝试
尝试用10个通道轮询发布消息,虽能延长无错误运行时间,但最终仍会触发该Frame Error。
疑问
- 使用
writeAll是否能保证无论底层缓冲区大小如何,都能一次性写入所有字节? - 是否可能由网络拥塞导致?当前约300 kb/s的负载理论上不应成为问题。
- 该错误的可能原因是什么?
内容的提问来源于stack exchange,提问作者skndstry
相关产品推荐
相关产品推荐

