跳转到内容

服务器网卡与网络

以太网与局域网扫盲

以太网(Ethernet)是一种网络技术,用于实现计算机之间的通信。

它是一种物理层和数据链路层的协议,定义了如何在物理介质(如双绞线、光纤等)上传输数据。

特点:

  • 物理层:定义了信号的电气特性、传输介质(如双绞线、光纤)等。
  • 数据链路层:定义了如何在物理介质上组织和传输数据帧(如 MAC 地址、帧格式等)。
  • 用途:以太网是最常用的局域网技术,广泛应用于家庭、办公室、数据中心等场景。
  • 标准:以太网的标准由 IEEE 802.3 定义,支持多种速率(如 10Mbps、100Mbps、1Gbps、10Gbps 等)。

局域(LAN,Local Area Network)是一种网络类型,指的是在有限地理范围内(如办公室、学校、家庭)的计算机网络。它是一种逻辑概念,描述了网络的拓扑结构和功能。

特点:

  • 范围:通常覆盖较小的地理范围(如一个建筑、一个校园)。
  • 用途:用于连接同一地点内的多台计算机,实现资源共享(如文件共享、打印机共享)和通信。
  • 技术:局域网可以使用多种技术实现,其中最常见的是以太网。但也可以使用其他技术,如 Wi-Fi(无线局域网)、Token Ring 等。
  • 拓扑结构:可以是星型、总线型、环型等。

查看网卡信息

ens 开头的网络接口:

ens 是 Linux 系统中常见的以太网接口命名方式,通常表示物理网卡或虚拟网卡。例如,ens192、ens33 等。

用于连接外部网络,支持网络通信,需要手动或通过网络管理工具进行配置。可以通过 ifconfig、ip、nmcli 等命令进行配置。

lo 网络接口:

用于本地主机内部的网络通信,系统自动配置,主要用于本地服务之间的通信和网络测试。

ifconfig与ip命令

bash
ifconfig ens192
ifconfig lo
ip a show ens192
ip a show lo

重点参数有mtu等。网卡的 MTU(最大传输单元)参数是可以修改的。MTU 定义了网络接口能够传输的最大数据包大小(以字节为单位)。默认情况下,以太网的 MTU 通常是 1500 字节,但在某些场景下(如使用 jumbo frames 或 VPN 等),可能需要调整 MTU 的值。

bash
sudo ip link set dev ens192 mtu 9000
sudo ifconfig ens192 mtu 9000

以上修改是临时性的,如果你使用的是 NetworkManager,可以通过以下方式持久化 MTU 配置:

bash
nmcli con mod ens192 ipv4.mtu 9000
nmcli con up ens192

nmcli con mod ens192 ipv4.mtu 9000:修改网卡 ens192 的 MTU 为 9000。

nmcli con up ens192:重新激活网卡以应用更改。

ethtool命令

bash
ethtool ens192
ethtool -i ens192

ethtool 是一个功能强大的数据链路层和物理层工具。用于查看和配置以太网卡的参数。ethtool -i ens192 和 ethtool ens192 的主要区别在于它们显示的信息内容和范围。

以下是两者的详细对比:

  • ethtool -i ens192

这个命令用于显示网卡的驱动程序信息,包括驱动程序的名称、版本、固件版本等。它主要关注网卡的硬件和软件驱动层面的信息。

输出结果:

driver: vmxnet3
version: 1.4.17.0-k-NAPI
firmware-version:
expansion-rom-version:
bus-info: 0000:0b:00.0
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: yes
supports-priv-flags: no

driver: vmxnet3

含义:网卡使用的驱动程序是 vmxnet3。

说明:vmxnet3 是 VMware 提供的高性能虚拟网卡驱动,专为虚拟机设计。

supports-test: no

含义:驱动程序不支持自检功能。

说明:无法使用 ethtool 进行硬件自检。

  • ethtool ens192

这个命令用于显示网卡的详细配置信息,包括速度、双工模式、自动协商、环回、链路状态等。它主要关注网卡的运行状态和配置参数。

输出结果:

Settings for ens192:
        Supported ports: [ TP ]
        Supported link modes:   1000baseT/Full
                                10000baseT/Full
        Supported pause frame use: No
        Supports auto-negotiation: No
        Supported FEC modes: Not reported
        Advertised link modes:  Not reported
        Advertised pause frame use: No
        Advertised auto-negotiation: No
        Advertised FEC modes: Not reported
        Speed: 10000Mb/s
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 0
        Transceiver: internal
        Auto-negotiation: off
        MDI-X: Unknown
Cannot get wake-on-lan settings: Operation not permitted
        Link detected: yes

Speed: 10000Mb/s

含义:当前网卡速度为 10Gbps。

说明:网卡当前运行在 10Gbps 的速度。

Duplex: Full

含义:当前双工模式为全双工。

说明:网卡运行在全双工模式,支持同时发送和接收数据。

Auto-negotiation: off

含义:自动协商功能关闭。

说明:网卡不会自动协商链路速度和双工模式。

总结:

  • 驱动程序:vmxnet3,版本 1.4.17.0-k-NAPI。
  • 网卡速度:10Gbps。
  • 双工模式:全双工。
  • 端口类型:双绞线(TP)。
  • 自动协商:关闭。
  • 链路状态:已连接。

这些信息表明你的虚拟网卡 ens192 当前运行在 10Gbps 的全双工模式,并且已成功连接到网络。由于这是虚拟网卡,某些功能(如自动协商和唤醒功能)可能不支持或受限。

除以上命令,还有实用的ethtool -S命令,用于查看网卡的高级统计信息,包括发送和接收的字节数、数据包数、错误数等。这些统计信息对于网络性能监控和故障排查非常有用。

bash
ethtool -S ens192

tx_packets 和 rx_packets 分别表示发送和接收的数据包数量,tx_errors 和 rx_errors 表示发送和接收的错误数据包数量。

如果这一层有问题,就会直接体现在网络层表现上面,比如 IP 会有丢包和延迟等现象,然后会引发传输层异常 (如丢包、乱序、重传等)。所以,一个稳定的数据链路层乃至物理层,是网络可靠性的基石。

TCP 的传输可靠性是通过序列号、确认号、重传机制等来保证的,通过这种机制,TCP 可以在一定程度的网络不稳定场景下,依然保证传输可靠,但不等于 TCP 可以无限容忍底层的不稳定,因为各种 TCP 拥塞控制算法都会因为这种问题, 而极大地降低传输性能。

ethtool -S的原理,是网卡驱动会到内核中注册 ethtool 回调函数,然后我们用 ethtool 命令就可以查看这些信息了。信息是由网卡驱动提供的。

网络连接命令:ss与netstat

ss和netstat的区别

了解当前系统开放了哪些端口,并且要查看开放这些端口的具体进程和用户。

netstat和ss都是网络相关的监控,netstat在协议栈中每一层都可以做监控统计:TCP、路由表、网络接口、协议等,但是在Linux中,netstat已经不为推荐,取而代之的是ss。

原理对比:

ss比netstat快的主要原因是,netstat是遍历/proc下面每个PID目录,ss直接读/proc/net下面的统计信息。所以ss执行的时候消耗资源以及消耗的时间都比netstat少很多。

当服务器的socket连接数量非常大时(如上万个),无论是使用netstat命令还是直接cat /proc/net/tcp执行速度都会很慢,相比之下ss可以节省很多时间。

ss快的秘诀在于,它利用了TCP协议栈中tcp_diag,这是一个用于分析统计的模块,可以获得Linux内核中的第一手信息。如果系统中没有tcp_diag,ss也可以正常运行,只是效率会变得稍微慢但仍然比netstat要快。

根据这篇博客的测试,同样的大量socket连接情况下,netstat和ss获取同样的统计数据时的耗时,ss明显比netstat少很多。

ss常用参数

和netstat类似,如-anlp等。

-a显示所有的sockets
-n显示数字IP和端口,不通过域名服务器
-l显示正在监听的
-p显示使用socket的对应的程序
-t只显示TCP sockets
-u只显示UDP sockets
-4 -6 只显示v4或v6V版本的sockets
-s打印出统计信息。这个选项不解析从各种源获得的socket。对于解析/proc/net/top大量的sockets计数时很有效
-0 显示PACKET sockets
-w 只显示RAW sockets
-x只显示UNIX域sockets
-r尝试进行域名解析,地址/端口

常用之统计:

ss -s

常用之查看端口:

ss -anlptu | grep端口

netstat常用参数

netstat -nap:显示系统端口使用情况
netstat -nupl:UDP类型的端口
netstat -ntpl:TCP类型的端口
netstat -na|grep ESTABLISHED|wc -l:统计已连接的,状态为"established"
netstat -l:只显示所有监听端口
netstat -lt:只显示所有监听tcp端口
netstat -rn:可以查看查看本机路由表、默认网关等信息
netstat -ntulp |grep 80: 查看所有80端口使用情况
netstat -nlp |grep LISTEN: 查看当前所有监听端口

netstat命令参数释义:

-r:--route,显示路由表信息
-g:--groups,显示多重广播功能群组组员名单
-s:--statistics,按照每个协议来分类进行统计。默认的显示IP、IPv6、ICMP、ICMPv6、TCP、TCPv6、UDP和UDPv6 的统计信息。
-M:--masquerade,显示网络内存的集群池统计信息
-v:--verbose,命令显示每个运行中的基于公共数据链路接口的设备驱动程序的统计信息
-W:--wide,不截断IP地址
-n:禁止使用域名解析功能。链接以数字形式展示(IP地址),而不是通过主机名或域名形式展示
-N:--symbolic,解析硬件名称
-e:--extend,显示额外信息
-p:--programs,与链接相关程序名和进程的PID
-t:所有的 tcp 协议的端口
-x:所有的 unix 协议的端口
-u:所有的 udp 协议的端口
-o:--timers,显示计时器
-c:--continuous,每隔一个固定时间,执行netstat命令
-l:--listening,显示所有监听的端口
-a:--all,显示所有链接和监听端口
-F:--fib,显示转发信息库(默认)
-C:--cache,显示路由缓存而不是FIB
-Z:--context,显示套接字的SELinux安全上下文

其他表述,常用参数-anplt

-a 显示所有活动的连接以及本机侦听的TCP、UDP端口
-l 显示监听的server port
-n 直接使用IP地址,不通过域名服务器
-p 正在使用Socket的程序PID和程序名称
-r 显示路由表
-t 显示TCP传输协议的连线状况
-u 显示UDP传输协议的连线状况
-w 显示RAW传输协议的连线状况

注意:在macos上,用法有些许不同,直接用可能报错缺少协议。

解决方案在Mac上正确使用的方法是:即-f需要加上地址族,-p需要加上协议TCP或者UDP等

如果需要查询inet,netstat -anvf inet
如果需要查询TCP, netstat -anvp tcp
如果需要查询UDP,netstat -anvp udp

time_wait数量与端口范围

查看time_wait数量:

netstat -ant | grep -i "time_wait" | wc -l

结果:13364

更加推荐以下这种格式的命令,显示格式更友好。

查看time_wait close_wait established 数量:

netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t", state[key]}'

结果:

CLOSE_WAIT 15
ESTABLISHED 1901
TIME_WAIT 572

查看端口范围,与linux内核参数相关:

cat /proc/sys/net/ipv4/ip_local_port_range

或者:

sysctl -a | grep ip_local_port_range

结果:32768 60999

查看网络连接历史统计信息

netstat -s | ss -s

netstat 除了可以获取实时连接状况,还可以获取历史统计信息。

比如,你怀疑 一台机器的网络很不稳定,除了用 ping 做简单的测试,你还可以用 netstat -s 来获取更加详细的统计信息。

比如,其中的 TCP 丢包和乱序计数值,就能帮助你判断传输层的状况。

以上是静态值,动态值可以配合watch命令查看:

bash
watch -d netstat -s

这个命令会把发生变化的数值进行高亮,方便我们查看。

用ss替代netstat:

bash
ss -s
bash
watch -d ss -s

netstat查看端口占用

bash
lsof -i:80

效果与下面类似:

bash
netstat -antp | grep 80

套接字socket相关

fconfig 和 ip 只显示了网络接口收发数据包的统计信息,但在实际的性能问题中,网络协议栈中的统计信息,我们也必须关注。

你可以用 netstat 或者 ss ,来查看套接字、网络栈、网络接口以及路由表的信息。

我个人更推荐,使用 ss 来查询网络的连接信息,因为它比 netstat 提供了更好的性能(速度更快)。

比如,你可以执行下面的命令,查询套接字信息:

netstat 和 ss 的输出也是类似的,都展示了套接字的状态、接收队列、发送队列、本地地址、远端地址、进程 PID 和进程名称等。

其中,接收队列(Recv-Q)和发送队列(Send-Q)需要你特别关注,它们通常应该是 0。当你发现它们不是 0 时,说明有网络包的堆积发生。当然还要注意,在不同套接字状态下,它们的含义不同。

当套接字处于连接状态(Established)时,

Recv-Q 表示套接字缓冲还没有被应用程序取走的字节数(即接收队列长度)。
而 Send-Q 表示还没有被远端主机确认的字节数(即发送队列长度)。

当套接字处于监听状态(Listening)时,

Recv-Q 表示 syn backlog 的当前值。
而 Send-Q 表示最大的 syn backlog 值。

而 syn backlog 是 TCP 协议栈中的半连接队列长度,相应的也有一个全连接队列(accept queue),它们都是维护 TCP 状态的重要机制。

顾名思义,所谓半连接,就是还没有完成 TCP 三次握手的连接,连接只进行了一半,而服务器收到了客户端的 SYN 包后,就会把这个连接放到半连接队列中,然后再向客户端发送 SYN+ACK 包。

全连接,则是指服务器收到了客户端的 ACK,完成了 TCP 三次握手,然后就会把这个连接挪到全连接队列中。这些全连接中的套接字,还需要再被 accept() 系统调用取走,这样,服务器就可以开始真正处理客户端的请求了。

协议栈统计信息

类似的,使用 netstat 或 ss ,也可以查看协议栈的信息。

-s参数的时候,这两个命令区别比较大,并不能互相替代,也不能比较哪个好,尤其警惕。

这些协议栈的统计信息都很直观。ss 只显示已经连接、关闭、孤儿套接字等简要统计,而 netstat 则提供的是更详细的网络协议栈信息。

比如,上面 netstat 的输出示例,就展示了 TCP 协议的主动连接、被动连接、失败重试、发送和接收的分段数量等各种信息。

以下分析ss -s的输出。

Total: 3555 (kernel 0)
TCP:   18860 (estab 1704, closed 16764, orphaned 0, synrecv 0, timewait 16415/0), ports 0

Transport Total     IP        IPv6
*         0         -         -
RAW       0         0         0
UDP       11        7         4
TCP       2096      1850      246
INET      2107      1857      250
FRAG      0         0         0

以上这个例子中,逐行解析如下:

1. Total: 3555 (kernel 0)
Total: 3555:表示当前系统中所有类型的套接字总数为 3555。
kernel 0:表示内核中没有未处理的套接字。
2. TCP: 18860 (estab 1704, closed 16764, orphaned 0, synrecv 0, timewait 16415/0), ports 0
TCP: 18860:表示 TCP 套接字的总数为 18860。
estab 1704:表示处于建立状态(ESTABLISHED)的 TCP 连接数量为 1704。
closed 16764:表示已经关闭的 TCP 连接数量为 16764。
orphaned 0:表示孤儿连接的数量为 0。孤儿连接是指那些已经关闭但尚未清理的连接。
synrecv 0:表示处于 SYN-RECV 状态的连接数量为 0。SYN-RECV 状态表示已经收到 SYN 包但尚未完成三次握手的连接。
timewait 16415/0:表示处于 TIME-WAIT 状态的连接数量为 16415。TIME-WAIT 状态是 TCP 连接关闭时的一个状态,用于确保所有数据包都已正确传输。
ports 0:表示当前没有监听的端口。
3. Transport Total     IP        IPv6
*         0         -         -:表示没有通用的套接字。
RAW       0         0         0:表示没有 RAW 套接字。
UDP       11        7         4:表示 UDP 套接字总数为 11,其中 7 个是 IPv4 的,4 个是 IPv6 的。
TCP       2096      1850      246:表示 TCP 套接字总数为 2096,其中 1850 个是 IPv4 的,246 个是 IPv6 的。
INET      2107      1857      250:表示 INET(TCP 和 UDP)套接字总数为 2107,其中 1857 个是 IPv4 的,250 个是 IPv6 的。
FRAG      0         0         0:表示没有分片的套接字。

总结汇总:

总套接字数量:3555
TCP 套接字总数:18860
建立状态(ESTABLISHED):1704
已关闭(CLOSED):16764
孤儿连接(ORPHANED):0
SYN-RECV 状态:0
TIME-WAIT 状态:16415
UDP 套接字总数:11
IPv4:7
IPv6:4
RAW 套接字总数:0
INET 套接字总数:2107
IPv4:1857
IPv6:250
分片套接字总数:0

Total 和 INET 的数量不一致,主要原因在于 Total 和 INET 统计的范围和内容有所不同。

Total 表示系统中所有类型的套接字总数,包括但不限于 TCP、UDP、RAW、UNIX 套接字等。它是一个更广泛的统计值,涵盖了所有类型的网络和非网络套接字,不仅仅是基于 IP 协议的套接字。例如,它还包括了 UNIX 套接字(用于本地进程间通信)和其他非 IP 套接字。

NET 表示基于 IP 协议族(包括 IPv4 和 IPv6)的套接字总数,主要包括 TCP 和 UDP 套接字。INET 的统计范围更窄,只关注基于 IP 协议的套接字。

因此,Total 的数量通常会大于或等于 INET 的数量。

TCP 总数 18860 是由以下几部分组成的:

已建立的连接:1704 已经关闭的连接:16764 孤儿连接:0 SYN-RECV 状态的连接:0 TIME-WAIT 状态的连接:16415

计算:1704 (estab) + 0 (orphaned) + 0 (synrecv) + 16415 (timewait) =

closed状态的这些连接已经完全关闭,不会计入总数。

TCP: 18860 和计算结果18115不一致。误差几百个连接,这可能是因为:

  • 统计时间差异:ss -s 命令在统计时可能存在时间差异,导致某些连接的状态在统计过程中发生了变化。
  • 内核状态差异:内核可能在统计过程中对某些连接进行了清理或状态更新。

参考资料

网速与流量监控

nload与iftop

bash
nload -m

查看各个网络接口的总体网速,普通用户即可运行,很常用。

bash
sudo apt/yum install nload

查看每个连接的网速,默认需要sudo权限

bash
sudo iftop

安装:

bash
sudo yum install iftop

查看详细端口流量占用情况,很常用:

bash
sudo iftop -i eth0 -P
sudo iftop -i ens192 -P

eth0是网络接口名,可以通过tcpdump/tshark -D知道所有的。

查看端口对应的进程

bash
sudo netstat -tunlp | grep $Port

这样就知道哪个进程的流量比较大。

此外还有一个需要sudo权限的bmon:

bash
sudo yum install bmon

sudo bmon -p ens192 # 实时查看某个网卡网速

iptraf实时监控流量

iptraf 命令来自英文词组 IP traffic monitor 的缩写,其功能是实时监视网卡流量。

iptraf 命令可以用来监视本地网络状况,能够生成网络协议数据包信息、以太网信息、网络节点状态及 IP 校验和错误等重要信息。

安装:

bash
sudo apt install iptraf/iptraf-ng

vnstat 查看网卡流量

局限性:要求大于4.18的内核版本。

vnstat 命令的功能是查看网卡流量的使用情况,是一个基于控制台的网络流量监控器。

vnstat 命令能够以每小时、每天、每月的时间跨度查看 Linux 系统中网卡流量的使用情况。

由 于 vnstat 命令读取的是 proc 目录内系统记录的流量信息,因此即便运维人员没有 root 管理员身份,也可以用该命令查看系统流量的统计情况。

安装:

bash
sudo apt install vnstat

启动:

bash
sudo service vnstatd start
sudo systemctl start vnstat

不启动就没有初始化数据库,使用会报错。

常用命令:

查询指定网卡的流量使用情况:

bash
vnstat -i eth0

更新数据库查看今天的流量使用情况:

bash
vnstat -d

更新数据库后查看本月的流量使用情况:

bash
vnstat -m

查看当前实时流量情况:

bash
vnstat -l

网络扫描工具nmap

nmap是一款功能强大的网络扫描工具,广泛用于网络安全、系统管理和网络诊断等领域。它可以帮助用户发现网络中的设备、识别开放的端口、检测运行的服务和操作系统类型等。

nmap常用命令示例

bash
nmap -Pn 192.168.12.104

-Pn参数:穿透防火墙进行扫描,扫描之前不需要用ping命令(有些防火墙禁止ping命令)。可以使用此选项进行扫描。

结果示例:

-v 参数:打印详细扫描过程。

bash
nmap -Pn -v 192.168.12.104

其他常用参数

  • -T4 : 设置时间模板,总共有T0-T5,比较适中的是T4
  • -p : 指定扫描端口
  • -n : 不进行DNS解析(反向解析IP地址到域名)
  • -sS : Nmap默认使用TCP方式扫描,需要完成完整的三次握手,很费时,所以这里可以采用-sS让Nmap使用SYN方式扫描。
  • –open : 只输出检测状态为open的端口,即开放的端口(输出结果的优化)
  • –host-timeout 30 : 检测超时的跳过(单位是秒 一般我们设置为30秒)

跨机与单机网络通信

单次跨机网络通信

本机IO不经过网卡

跨机与本机特点对比

192.x.x.x == 127.0.0.1 ==loopback==lo虚拟网卡

首先,本机IP(比如192.x.x.x)和127.0.0.1没有差别,都是走的环回设备lo。

其次,只要是本地网络,都不需要经过网卡,即使网卡拔了也可以正常使用本机网络。

这是因为内核在设置IP的时候,把所有的本机IP都初始化到了local路由表里,类型写死了是RTN_LOCAL。所以后面的路由项选择的时候发现类型是RTN_LOCAL就会选择lo设备。

数据包在内核中是什么走向,和外网发送相比流程上有什么差别?

  • 节约了驱动上的一些开销。发送数据不需要进入RingBuffer的驱动队列,直接把skb传给接收协议栈。
  • 其他组件,包括系统调用、协议栈、设备子系统都经过了,甚至驱动程序也运行了,所以还是有一定的开销的。
  • 如果想要再本机网络IO上绕开协议栈的开销,可以动用eBPF,用eBPF的sockmap和sk redirect可以达到真正不走协议栈的目的。

思考:单机比跨网到底快多少?如何控制变量对比?