Linux服务器网卡深度解析:从ifconfig输出到生产环境性能调优实战
- Linux服务器网卡深度解析:从ifconfig输出到生产环境性能调优实战
- 一、背景
- 二、生产环境的服务器部署情况
- 三、拆解一个真实的 ifconfig 输出
- 1、先看 MAC 地址
- 2、再看设备的 interrupt 和 memory
- 3、了解Linux网卡的命名规则
- 四、流量流向的情况
- 五、虚拟机 ifconfig 的情况
- 六、总结
Linux服务器网卡深度解析:从ifconfig输出到生产环境性能调优实战
一、背景
2025年4月9号,客户对我们生产环境的接口进行了15000TPS的压力测试,客户在微信群里反馈,只能压测到9000左右,速度上不去了。
看到这个消息之后,我有两个反应:
1、情绪方面,讲真我是有点生气的,想骂人,但还忍住了。
客户在我们不知情的情况下,对生产环境的接口做压力测试,TPS这么高,容易把带宽打满,会影响到其他客户;我能理解客户为什么不提前告知,大概率就是想出其不意,防止我们事先做准备,但这做法确实比较负面和负能量;要么就是我自己想多了,对方的技术人员没有意识到这种问题会产生什么影响。
2、要赶紧查看一下,带宽是否被打满,是不是影响其他客户。
由此涉及到了本次想分享的主题,作为一个 Linux 后端开发,我也经常使用 ifconfig 命令查看一些信息,但从来没有深究过,今天是想总结一下了。
这么多年的开发经验,进过运营商机房、见过机房里面的机架、服务器。大学期间,组装过台式机(算是见过网卡),安装过操作系统(要安装网卡驱动的),也就仅限于此。
所以今天,我想分享一下如何根据 ifconfig 命令理解网卡信息和网卡流量。
二、生产环境的服务器部署情况
客户的流量,经过公网到达我们北京机房,首先是经过防火墙设备、然后到达nginx服务器(10.90.36.248),经过nginx的转发最后到达后端业务程序(10.90.36.117、10.90.36.118)。
这期间,流量还会经过路由器和交换机,我还不太清晰,但不影响理解,也就不列出来了。
1、10.90.36.248 服务器是一台物理机,安装了 nginx,用作负载均衡;
2、10.90.36.117、10.90.36.118 服务器是一台虚拟机,部署业务程序,用作后端服务;
三、拆解一个真实的 ifconfig 输出
下面这段 来自于 10.90.36.248 nginx 服务器的 ifconfig 命令的输出。
可以看到好几个网卡信息,比如:bond1、bond1:1、enp8s0f0、enp8s0f1、enp8s0f2、enp8s0f3、ens2f0、ens2f1、lo,该如何拆解呢?
凭直觉,我们可以给这些网卡进行分类:
1、bond1、bond1:1
2、enp8s0f0、enp8s0f1、enp8s0f2、enp8s0f3
3、ens2f0、ens2f1、
4、lo
大家应该能猜到,这其中有真实的物理网卡、也有虚拟出来的虚拟网卡(或者叫逻辑网卡)。
那怎么区分哪些是物理网卡,哪些是虚拟网卡?
[app@phy01 ~]$ ifconfig
bond1: flags=5187<UP,BROADCAST,RUNNING,MASTER,MULTICAST> mtu 1500
inet 10.90.36.248 netmask 255.255.255.0 broadcast 10.90.36.255
inet6 fe80::327b:acff:fe77:37d8 prefixlen 64 scopeid 0x20<link>
ether 20:6b:ac:67:32:d9 txqueuelen 1000 (Ethernet)
RX packets 1391424129086 bytes 401438743483080 (365.1 TiB)
RX errors 124693 dropped 17 overruns 124633 frame 60
TX packets 1262250505591 bytes 198488434823174 (180.5 TiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
bond1:1: flags=5187<UP,BROADCAST,RUNNING,MASTER,MULTICAST> mtu 1500
inet 10.90.36.238 netmask 255.255.255.255 broadcast 0.0.0.0
ether 20:6b:ac:67:32:d9 txqueuelen 1000 (Ethernet)
enp8s0f0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether 77:ee:cb:75:22:21 txqueuelen 1000 (Ethernet)
RX packets 13422608 bytes 1789398012 (1.6 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xc7360000-c737ffff
enp8s0f1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether 77:ee:cb:75:22:22 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xc7340000-c735ffff
enp8s0f2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether 77:ee:cb:75:22:23 txqueuelen 1000 (Ethernet)
RX packets 27993427 bytes 10295585352 (9.5 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xc7320000-c733ffff
enp8s0f3: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether 77:ee:cb:75:22:24 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xc7300000-c731ffff
ens2f0: flags=6211<UP,BROADCAST,RUNNING,SLAVE,MULTICAST> mtu 1500
ether 20:6b:ac:67:32:d9 txqueuelen 1000 (Ethernet)
RX packets 1391340237564 bytes 401431888921467 (365.1 TiB)
RX errors 124693 dropped 8 overruns 124633 frame 60
TX packets 1262250505591 bytes 198488434823174 (180.5 TiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 80 memory 0x23fff000000-23fff7fffff
ens2f1: flags=6211<UP,BROADCAST,RUNNING,SLAVE,MULTICAST> mtu 1500
ether 20:6b:ac:67:32:d9 txqueuelen 1000 (Ethernet)
RX packets 83891522 bytes 6854561613 (6.3 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 100 memory 0x23ffe000000-23ffe7fffff
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
RX packets 825841 bytes 110153455 (105.0 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 825841 bytes 110153455 (105.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[app@phy01 ~]$
1、先看 MAC 地址
我们知道 MAC 地址是用来唯一标识一个设备的,所以,我们可以通过 MAC 地址来区分物理网卡和虚拟网卡。
在 ifconfig 命令的输出中,ether 指的就是 MAC 地址。
你会发现,bond1、bond1:1、ens2f0、ens2f1 的MAC 地址都是 20:6b:ac:67:32:d9,
那这些都是同一个物理网卡吗?
而 enp8s0f0、enp8s0f1、enp8s0f2、enp8s0f3 的 MAC 地址也有规律,分别是:
77:ee:cb:75:22:21
77:ee:cb:75:22:22
77:ee:cb:75:22:23
77:ee:cb:75:22:24
那这些是不同同的物理网卡吗?
2、再看设备的 interrupt 和 memory
device interrupt 是设备的中断号,而 device memory 是设备的内存地址。
这两个属性,是操作系统分配给硬件的资源,可以用来作为是不是物理网卡的直接证据。
虽然 bond1、bond1:1、ens2f0、ens2f1 的MAC 地址都是 20:6b:ac:67:32:d9,但
ens2f0 的 interrupt 是 80,memory 是 0x23fff000000-23fff7fffff
ens2f1 的 interrupt 是 100,memory 是 0x23ffe000000-23ffe7fffff
而 bond1、bond1:1 是没有interrupt 和 memory 的。
通过这些信息,我们可以知道,
bond1 是一个绑定主接口(有 MASTER 标志),聚合了 ens2f0 和 ens2f1 (有 SLAVE 标志 并且 他们有相同 MAC 地址),
bond1还具有两个 IP 地址,主地址 10.90.36.248 和 别名地址 10.90.36.238(bond1:1 是 bond1 的别名接口)。
所以可以得知, ens2f0 和 ens2f1 大概率是:一个独立的含有2个端口的真实物理网卡。
而 bond1 是基于 ens2f0 和 ens2f1 的虚拟网卡。
bond1:1 又是基于 bond1 的别名。
对 enp8s0f0、enp8s0f1、enp8s0f2、enp8s0f3 的理解就比较简单了,他们都有不同的 MAC地址,也有不同的device memory,
所以大概率是:一个独立的含有4个端口的真实物理网卡。
3、了解Linux网卡的命名规则
从上面的ifconfig输出中,我们看到了各种各样的网卡名称,如ens2f0、enp8s0f0等。这些名称并非随意取的,而是遵循了Linux网卡的命名规则,也称为"可预测网络接口名称"(Predictable Network Interface Names)。
在传统的Linux系统中,网卡命名通常是eth0、eth1这样的格式。但这种命名方式存在一个问题:当系统重启或硬件变更时,网卡的顺序可能会改变,导致eth0变成eth1,反之亦然。为了解决这个问题,现代Linux系统采用了更可预测的命名方案:
-
ens2f0的命名解析:
- en: 表示Ethernet,即以太网设备
- s2: 表示插槽(slot)2
- f0: 表示该插槽上的第一个端口(function 0)
-
enp8s0f0的命名解析:
- en: 表示Ethernet
- p8: 表示PCI总线号8
- s0: 表示该总线上的插槽0
- f0: 表示该插槽上的第一个端口
-
bond1:
- 这是一个虚拟接口,通过将多个物理接口绑定在一起组成的
- 数字1表示这是系统中的第二个bond接口(从0开始计数)
-
lo:
- 代表loopback,即回环接口
- 用于本机通信,IP地址为127.0.0.1
了解这些命名规则有助于我们仅通过网卡名称就能识别出网卡在系统中的物理位置,以及它们的类型和功能。
四、流量流向的情况
我们继续看生产环境,流量是如何流向的情况。
bond1入站、ens2f0入站,都是 101.16Mb/s
bond1出站、ens2f0出站,都是 108.14Mb/s
在绑定模式中,流量默认只通过一个从属接口(ens2f0)接收,另一接口(ens2f1)处于备用状态,因此 ens2f0 的入站流量与 bond1 完全一致。
至于入站流量与出站流量不一致,是因为nginx服务器会添加一些HTTP请求头导致的差异。
五、虚拟机 ifconfig 的情况
在我们的生产环境中,还有很多的虚拟机,它们的 ifconfig 更简单,再来看一个虚拟机下的 ifconfig 的输出。
[root@kundebug ~]$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.18.249.178 netmask 255.255.240.0 broadcast 172.18.255.255
inet6 fe80::216:3eff:fe08:efe8 prefixlen 64 scopeid 0x20<link>
ether 00:16:3e:08:ef:e8 txqueuelen 1000 (Ethernet)
RX packets 6651745 bytes 2931130548 (2.7 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5152881 bytes 3191851949 (2.9 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@kundebug ~]$
在这台虚拟机的 ifconfig 输出中,看不到 device interrupt 和 device memory 信息。
而根据 MAC 地址 00:16:3e:08:ef:e8 的前3个字节 00:16:3e ,我们可以在IEEE官网上查到这个 MAC 地址的厂商信息,如下:
前3字节 00:16:3e 属于 Xensource(常见于虚拟化环境,如 Xen/KVM)。
所有合法的 MAC 地址都可以通过 IEEE 官网查询到它的厂商信息,每个 MAC 地址为全球唯一。
当然如果你用本文前面 ifconfig 输出的信息中的 MAC 来查询,是查不到的,因为已经被我修改过了,哈哈哈哈。
当然这个很好验证了,我找了我们测试环境的一台物理机,查到的厂商是华为的,这没有问题。
六、总结
通过本文的分析,我们可以得出以下几点关于Linux服务器网卡信息的理解要点:
-
物理网卡与虚拟网卡的区分:
- 物理网卡通常具有唯一的MAC地址,且会分配有device interrupt和device memory
- 虚拟网卡(如bond接口)通常没有device interrupt和memory信息
- 虚拟机中的网卡(如eth0)虽然有MAC地址,但其MAC地址前缀通常表明其为虚拟化厂商分配
-
网卡命名规则:
- ens2f0这类命名通常表示物理网卡接口,其中数字标识不同的插槽和端口
- bond接口是将多个物理网卡绑定为一个逻辑接口,提高吞吐量和冗余性
- 像bond1:1这样的别名接口允许在同一物理接口上配置多个IP地址
-
流量分析:
- 通过RX/TX packets和bytes可以监控网络流量
- 在bond模式下,流量可能只通过一个活跃的从属接口传输,其他接口处于备用状态
- 关注errors、dropped、overruns等计数器可以帮助发现潜在的网络问题
-
实际应用价值:
- 了解网卡信息有助于定位网络瓶颈,如本文开头提到的客户压测场景
- 对于后端开发人员,这些知识在性能优化和问题排查时非常宝贵
- 在高流量环境下,了解网卡配置可以帮助判断是否需要硬件升级或配置调整
-
MAC地址识别:
- MAC地址的前3个字节(OUI)可以标识厂商
- 通过IEEE官网可以查询MAC地址的厂商信息
- 这有助于判断网卡的来源和类型(物理/虚拟)
作为Linux后端开发人员,掌握这些网络基础知识不仅有助于日常运维和问题排查,也能在系统设计和性能优化时做出更明智的决策。在高并发、高流量的生产环境中,这些知识尤为重要,可以帮助我们快速定位问题根源,提供更可靠的服务。