最近做了一次网络抖动排障,庆幸定位到了原因,记录一下。
网络抖动的表现
业务方是 DB 团队,他们对慢查询有监控,发现了一些慢查询;而且,确认是接入虚拟网络后才出现的慢查询。
所以,他们确信是我这边的问题,于是联系到了我这边。如下,是我同事做的 ping 记录:
1
2
3
4
5
6
7
8
9
10
11
|
# cat ping_log | grep -v "time=0"
PING x.x.x.x (x.x.x.x) 56(84) bytes of data.
64 bytes from x.x.x.x: icmp_seq=3415 ttl=62 time=197 ms
64 bytes from x.x.x.x: icmp_seq=3416 ttl=62 time=173ms
64 bytes from x.x.x.x: icmp_seq=3417 ttl=62 time=149ms
64 bytes from x.x.x.x: icmp_seq=3418 ttl=62 time=125 ms
64 bytes from x.x.x.x: icmp_seq=3419 ttl=62 time=101 ms
64 bytes from x.x.x.x: icmp_seq=3420 ttl=62 time=77.3 ms
64 bytes from x.x.x.x: icmp_seq=3421 ttl=62 time=53.3 ms
64 bytes from x.x.x.x: icmp_seq=3422 ttl=62 time=29.3 ms
64 bytes from x.x.x.x: icmp_seq=3423 ttl=62 time=5.27 ms
|
我也用 ping -i 0.02 x.x.x.x
确认了一下,的确是这样,几千个 ping 包中,有几个包的延迟很高。
排查过程
首先,我确认了一下虚拟网络网关的环境设置,发现有点问题;于是,我修改了一下,但是问题依旧。
然后,我怀疑是 CPU 抢占的问题;于是,用 htop -d 0.2
看了一下,发现 CPU 使用率并不高;不过,恰巧注意到 ethtool -m XXX
会定期执行一下;接着,用 bpftrace execsnoop.bt
确认了一下,的确是这样:
1
2
3
4
5
6
7
|
# bpftrace /usr/sbin/execsnoop.bt
Attaching 2 probes...
TIME (ms) PID ARGS
1361 1844976 ethtool -m XXX0
2117 1844977 ethtool -m XXX1
6774 1844978 ethtool -m XXX0
7118 1844979 ethtool -m XXX1
|
不过,execsnoop.bt
没提供 PPID,不知道是哪个进程在执行 ethtool -m XXX
;于是,我用 for i in {1..100}; do ps -ef | grep ethtool; sleep 0.1; done
确认了一下 PPID,居然是某个 exporter 在执行 ethtool -m XXX
。
经同事一起确认,ethtool -m XXX
会影响 Intel 网卡收发包,从而导致网络抖动。
随后,让负责 exporter 的同事,修改了一下代码,不再执行 ethtool -m XXX
;问题解决。
ixgbe
网卡驱动
ethtool -i XXX
确认网卡驱动是 ixgbe
,于是,我看了一下 ixgbe
网卡驱动的源代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
// ${KERNEL}/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
static int ixgbe_get_module_info(struct net_device *dev,
struct ethtool_modinfo *modinfo)
{
// ...
/* Check whether we support SFF-8472 or not */
status = hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_SFF_8472_COMP,
&sff8472_rev);
// ...
/* addressing mode is not supported */
status = hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_SFF_8472_SWAP,
&addr_mode);
// ...
return 0;
}
static int ixgbe_get_module_eeprom(struct net_device *dev,
struct ethtool_eeprom *ee,
u8 *data)
{
// ...
for (i = ee->offset; i < ee->offset + ee->len; i++) {
/* I2C reads can take long time */
if (test_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
return -EBUSY;
if (i < ETH_MODULE_SFF_8079_LEN)
status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
else
status = hw->phy.ops.read_i2c_sff8472(hw, i, &databyte);
if (status)
return -EIO;
data[i - ee->offset] = databyte;
}
return 0;
}
static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_module_info = ixgbe_get_module_info,
.get_module_eeprom = ixgbe_get_module_eeprom,
};
|
发现,ethtool -m XXX
会读取网卡的硬件信息,估计是这些操作影响了网卡的收发包。
总结
庆幸的是,那个 exporter 用的是 ethtool -m XXX
命令行来获取信息,而不是用 ioctl()
系统调用;否则,我可能就找不到原因了。
所以,有没有办法对 ethtool
使用的 ioctl()
系统调用进行监控呢?kprobe dev_ethtool()
即可。