一、凌晨三点的报警
去年双十一压测,集群里某个存储节点突然报出大量“retry_exceeded”错误。监控面板上IB端口的丢包率不到0.01%,但业务层的写IO延迟从50μs直接飙到800ms。当时第一反应是怀疑网卡固件bug,结果抓了整整两天的包才发现——问题出在QP(Queue Pair)的超时参数配置上。
那个场景很典型:两个节点之间通过RC(可靠连接)传输元数据,发送端连续发了128个4KB的WR(Work Request),接收端因为CPU忙,处理CQ(Completion Queue)的速度跟不上。发送端在等待ACK的过程中,重试计数器被耗尽,QP直接进入ERR状态。更坑的是,业务代码里没有做QP重建的逻辑,整个连接就卡死了。
二、QP超时到底在等什么
先看一个最容易被误解的参数:timeout。在ibv_qp_attr结构体里,这个字段的单位是“2的幂次方微秒”。比如设置timeout=12,实际超时时间是2^12 = 4096微秒,约4毫秒。但很多人以为这是“发送后等待ACK的最大时间”,其实不对。
RDMA的超时机制是分层的。发送端发出一个请求后,硬件会启动一个定时器。如果在这个时间内没有收到接收端的ACK或NAK,硬件会触发一次重传。注意,这个定时器是从“发送完成”开始计时的,而不是从“数据到达对端”开始。所以如果网络延迟本身就有1ms,你设个2ms的超时,基本每次都会触发重传。
我踩过的一个坑:在跨机房场景下,两个数据中心之间的RTT(往返时间)大约是1.5ms。当时把timeout设成了10(210=1024μs≈1