一、先搞清楚排队积压是怎么发生的
生产环境里,交易排队积压就像是超市里排队结账的人越来越多。蚂蚁链节点内部其实也有一套“结账系统”:交易进来之后,先进入一个等待名单,这个名单在技术上叫交易池或者交易缓存。节点慢慢处理这些交易,处理完一笔,就把它写进账本,然后通知外面的人“这笔已经收到了”。
正常情况下,进来的人和结账速度是匹配的,队伍不会太长。可一旦某个环节变慢,队伍就越排越长。这个时候,最让人头疼的问题是:到底是因为超市门口顾客进来太快,还是因为收银员手太慢?
对应到技术上,进来太快往往和网络有关,收银员太慢则常常和磁盘读写有关。但实际情况没那么简单,网络瓶颈不只是“进来的交易太多”,磁盘瓶颈也不只是“写文件慢”,它们会互相影响。所以我们需要靠节点本身的性能指标,一点一点拆开看。
二、别慌,先找两张“体检表”
判断瓶颈之前,先要明白该看哪些指标。电脑和服务器也是需要“体检”的,上面有很多计数器在记录自己的状态。我们要重点看三张表:网络体检表、磁盘体检表、CPU附带的一张“等待I/O”的记录表。
网络体检表里最主要的是网卡流量、重传率、丢包率、连接数。磁盘体检表里最主要的是磁盘使用率(util)、平均I/O等待时间(await)、I/O队列长度。CPU的那张表里,有个很显眼的数字叫 iowait,意思是CPU有多少时间在“干瞪眼”等着磁盘把数据写好。
这些名字听起来硬邦邦的,但你可以把它们当成体温、血压、心率。我们不是要背所有参数,只需要知道每个数字高了代表什么。
2.1 常用的查看工具
平时最常打交道的有三个命令:iostat、sar、ss。iostat 是磁盘的“听诊器”,专门看硬盘忙不忙;sar 是系统的“录像机”,能记录网络吞吐和队列情况;ss 是连接状态的“显微镜”,可以看当前节点到底建立了多少连接,每个连接在做什么。下面快速演示一下 ss 的用法,技术栈为 Shell:
# 查看当前系统所有TCP连接的状态汇总
ss -s
# 查看本机8080端口上已经建立的连接数量
ss -tan | grep 8080 | wc -l
iostat 和 sar 需要用到 sysstat 包,安装之后就可以直接使用了。大多数Linux发行版都支持通过包管理器安装。平时排查的时候,这三条命令已经能覆盖七八成的问题。
三、如何用这些指标分辨瓶颈
3.1 先看磁盘忙不忙
当交易积压的时候,第一反应应该去看磁盘。因为蚂蚁链每个节点都要不停地把交易记录写到账本上,这个动作躲不开。如果磁盘使用率接近100%,比如 %util 已经跑到97%以上,那基本可以断定磁盘已经累趴下了。
另外还要看 await。这个数字是磁盘完成一次读写要等多久。如果它从平时的几毫秒涨到几十毫秒,说明每次读写都要排很长的队。想象一下,收银员每扫一件商品都要等10秒才能读到条码,这队伍肯定越长越多。
3.2 再看网络堵不堵
如果磁盘看起来还好,没有那么高的使用率,那我们就要跑到网络的区域去看。首先要看网卡流量有没有逼近带宽上限。比如一台机器是千兆网卡,理论上每秒能传约125MB数据,但如果你看到它已经稳定在110MB以上,那就说明网卡已经快被塞满了。
如果你想确认网卡是不是真的千兆,可以在Linux上使用下面的Shell命令:
# 查看eth0的协商速率和双工模式
ethtool eth0 | grep Speed
紧接着还要看TCP重传率。如果网络太堵,数据包丢了一部分,发送方就要重新发送,这一现象会直接反映在重传率上。你可以把它想象成快递员在泥泞路上不断回头去捡掉落的东西,活全白干了一半。
3.3 最关键的一招:结合iowait和软中断
这里有一个特别能帮忙分辨的细节:当磁盘是瓶颈时,CPU有很大一部分时间都在等磁盘,所以 iowait 会明显偏高。但如果网络是瓶颈,iowait 通常不高,反而是网卡收包触发的“软中断”会占用不少CPU,你可能会看到 sy(系统态)CPU比例升高。
所以,当你看到交易积压,而且 iowait 高,优先怀疑磁盘;看到网络吞吐逼到上限,与此同时 iowait 不高,优先怀疑网络。如果两个都高,那就要继续看是谁先引起的,比如是不是磁盘慢导致处理慢,进而导致网络发送和接收的吞吐都降下来了,看起来像网络堵。
3.4 注意峰值和平均值的差别
还有一点很重要:看指标不能只看一秒,要看持续一段时间的趋势。有些时候网络流量只是在某个秒级突然冲高,马上又掉下来,这样的峰值会瞬间把队列塞爆,但平均下来却不高。所以我们诊断时要采样几十秒甚至几分钟,不能只截一张图就下结论。
四、用Shell命令现场采样,把证据拿在手里
为了让大家能直接上手,这里用Shell技术栈写一个小脚本。它会在节点上同时采集磁盘和网络的关键指标,并给出一个初步判断。注意脚本需要安装 sysstat 包,里面提供了 iostat 和 sar 这两个帮手。
#!/bin/bash
# 文件名: check_blocking.sh
# 作用: 快速判断当前节点是网络瓶颈还是磁盘瓶颈
# 使用方法: bash check_blocking.sh
echo "======== 开始采样 ========"
date
# 用iostat采集磁盘扩展统计,每1秒采一次,共3次
# -x: 显示扩展使用率 -d: 只看磁盘设备 1 3: 间隔和次数
iostat -dx 1 3
echo "----------------------"
# 用sar采集网络设备统计,同理也是每1秒采一次,共3次
# -n DEV: 报告网络设备活动, eth0 需要根据自己的网卡名改一下
sar -n DEV 1 3
echo "----------------------"
# 查看TCP协议层的统计信息里和重传相关的行
netstat -s | grep -E "segments retransmited|TCPLostRetransmit"
echo "======== 采样结束 ========"
echo "接下来请对比:"
echo "1. 如果磁盘 %util > 90, 且 await 很高, 优先怀疑磁盘。"
echo "2. 如果网卡rxkB/s接近带宽上限, 且重传率明显升高, 优先怀疑网络。"
echo "3. 如果 iowait 高, 多半是磁盘; 如果 sy%CPU高而 iowait不高, 多半是网络。"
解释一下脚本里每个命令的用途。iostat -dx 1 3 会把磁盘设备的使用率、读写速率、平均I/O时间一行行列出来。sar -n DEV 1 3 会打印网卡的每秒收发包数和字节数,比如最关心的 rxkB/s 和 txkB/s。netstat -s 则把TCP层面的统计信息翻出来,重点看有没有很多的重复包。
有了这些原始数据,我们可以写一段简单的Shell逻辑来自动提出一个初步结论。下面这个片段用固定数字模拟了采集后的结果,主要演示判断思路:
#!/bin/bash
# 模拟一次分析过程,假设我们采集到以下数值
DISK_UTIL=97.5 # 磁盘使用率,单位%
IO_AWAIT=48.5 # 平均IO等待时间,单位ms
NET_RX_MBPS=112 # 网卡接收速率,单位MB/s
NET_LIMIT=125 # 千兆网卡的理论上限,单位MB/s
if [ "$(echo "$DISK_UTIL > 90" | bc)" == "1" ]; then
if [ "$(echo "$IO_AWAIT > 20" | bc)" == "1" ]; then
echo "磁盘响应已经明显变慢,优先排查磁盘读写的瓶颈。"
fi
fi
if [ "$(echo "$NET_RX_MBPS > $NET_LIMIT * 0.85" | bc)" == "1" ]; then
echo "网络接收速率已经超过带宽上限的85%,网络也可能成为拦路虎。"
fi
这里用到了 bc 命令来做小数比较。如果没有安装,可以用整数的近似判断,或者把系数乘以100再比较。这段脚本只是把思路变成程序,真正开工的时候,你还要把它接到监控系统里,持续输出。
五、真实场景:一次排除“假网络瓶颈”的经历
举个例子。某次蚂蚁链生产环境出现交易积压,第一感觉是“是不是网络带宽跑满了?”结果用上面的脚本一跑,发现网卡接收速率只有40MB/s,离上限远得很。反而磁盘 %util 一直是99%,await 从正常的5毫秒涨到了60毫秒。这时候真相大白:磁盘太忙,导致交易处理速度降下来,队列自然越积越长。网络看起来不忙,是因为处理太慢,根本吞不下更多流量。
还有一次,情况反过来。磁盘很轻松,但网络发送速率已经贴着上限跑。进一步检查,发现TCP重传率比平时涨了10倍。这是因为出口带宽被占满,数据包排队发送延迟很高,对端等不及就重发了。之后我们把某些消息做压缩,并调大了发送缓冲区,积压就缓过去了。
这个例子告诉我们:不要凭感觉,一定要看数字。而且两个指标要交叉着看,不能被单一项带偏。
六、优化方案各自的优缺点和注意事项
6.1 应对磁盘瓶颈的方案
如果确认是磁盘慢,常见的做法是换用更快的SSD/NVMe盘,或者把账本数据放到内存盘上。还有一种办法是减少写次数,比如把多条交易合并成一个批次再写一次。这样做的好处是吞吐量立刻能提高,坏处也很明显:批次处理会增加一点延迟,而且内存盘数据丢失风险高,需要做好冷备。
6.2 应对网络瓶颈的方案
网络带宽不够的时候,通常会做几件事:一是扩带宽,比如把千兆网卡换成万兆;二是减少传输数据量,比如对交易内容做压缩,或者把不必要的大字段裁剪掉;三是做流控,在节点入口限制每秒进来的交易数量,这样队列就不会被瞬时冲爆。
扩带宽最直接,但成本高;压缩和裁剪效率高,但可能影响兼容性,需要测试所有场景;流控能缓解排队,但会让交易看起来“变慢”,需要配合外部轮询策略。
6.3 所有方案都要注意的事
第一,所有优化都要先在测试环境验证,不能直接在生产环境乱改。第二,性能指标要长期采集,设置告警,比出问题后再排查好得多。第三,蚂蚁链是去中心化系统,单个节点变慢会影响整条链,所以观察指标时最好把多个节点放在一起看,确认问题是局部还是一大片。第四,网络和磁盘有时候会互相“伪装”,比如磁盘慢会让本节点确认消息发得慢,对端因为收不到确认就会重发,导致网络重传率高,看起来像网络问题。最靠谱的方法还是同时看iowait、磁盘util、网络带宽和重传率,然后根据比例判断罪魁祸首。
七、总结
交易排队积压并不可怕,可怕的是不知道去哪看指标。本文从“进来速度快”和“处理速度慢”这两个角度出发,带着你走了完整的分辨流程。简单来说,先看磁盘使用率和await,再看网络带宽和重传率,最后用iowait和CPU软中断来修正判断。你完全可以用那套Shell脚本快速拿到关键证据。记清楚:磁盘瓶颈时iowait高、磁盘util高、网络未必满;网络瓶颈时网卡接近带宽上限、重传率高、磁盘指标正常。多练几次,你就能在积压问题暴发的时候,稳稳地找到真正的病根,然后对症下药。
评论
围绕“蚂蚁链生产环境不断出现交易排队积压现象时,如何利用节点性能指标精准分辨网络瓶颈与磁盘读写瓶颈所在?”参与讨论