监控网络状态

监控网络状态

netstat network statistics

Linux netstat 命令用于显示网络状态。

利用 netstat 指令可让你得知整个 Linux 系统的网络情况。

netstat 命令很简单,也很直接,用于显示与 IP、TCP、UDP 和 ICMP 协议相关的统计数据,一般用于检验本机各端口的网络连接情况。netstat 是在内核中访问网络及相关信息的程序,它能提供 TCP 连接,TCP 和 UDP 监听,进程内存管理的相关报告。

netstat [-acCeFghilMnNoprstuvVwx][-A<网络类型>][--ip]

参数

提示:LISTEN 和 LISTENING 的状态只有用 -a 或者 -l 才能看到

常用 -a -n -p

使用 root 权限运行 netstat -anp,输出

……

从整体上看,netstat 的输出结果可以分为两个部分:

一个是 Active Internet connections,称为有源 TCP 连接,即网络连接,我们用 netstat 命令看的主要也是这个部分,

我们可以很明显地看到 22 端口的监听(SSH):

172.16.20.1,指的其实就是 Linux 的宿主机:Windows,也就是我的 xshell 的所在的电脑,

所以这里实际上就是从宿主机的 55750 端口到虚拟机的 22 端口的一个 ssh 网络连接。

如果有多条,说明 xshell 里开了多个 ssh 连接。

一旦用户退出,ssh 连接断开,这一条网络连接信息就会消失,有时候也会有 TIME-WAIT 的中间过渡状态(这是由 TCP 协议的机制决定的)。

另一个是 Active UNIX domain sockets,称为有源 Unix 域套接口 (和网络套接字一样,但是只能用于本机通信,也就是本机内部的通信性能可以提高一倍)。

State 的类型


本地 IP 地址和远程 IP 地址都是 0.0.0.0,这表示通信还没开始,IP 地址不确定,进程的状态也是 LISTEN

UDP 协议中套接字不绑定对方的地址和端口,因此这里显示 *:*

这部分《网络是怎样连接的》的《用电信号传输 TCP/IP 数据 —— 探索协议栈和网卡》的 套接字的实体就是通信控制信息


常用:

netstat -i:显示网卡列表,跟 ifconfig 查看的结果一样

netstat -a:列出所有端口 (包括监听和未监听的)

netstat -at:列出所有 TCP 协议端口

netstat -au:列出所有 UDP 协议端口

netstat -l:只显示正在监听的端口

netstat -lt:只显示正在监听的 TCP 端口

netstat -lu:只显示正在监听的 UDP 端口

netstat -s:显示所有端口的统计信息

netstat -st:显示 TCP 端口的统计信息

netstat -su:显示 UDP 端口的统计信息

netstat -ap,列出所有端口,加上进程信息 -p

netstat -c:将每隔一秒输出网络信息。

经常是对 netstat -anp 的结果再进行二次的搜索 ,比如

netstat -anp | grep ssh

netstat -anp | grep ':80'

……

常见问题处理

大量的 TCP 连接的状态为 CLOSE_WAIT

背景知识

参考《网络是怎样连接的》的《用电信号传输 TCP/IP 数据 —— 探索协议栈和网卡》的 数据收发操作小结 小节

原因

Linux 服务器 tcp socket 常见的几种状态:ESTABLISHED、TIME_WAIT、CLOSE_WAIT。

TCP 协议中描述,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于假死状态,连接本身占用的资源不会被释放。

提供网络服务时,需要特别关注两种状态:CLOSE_WAIT 和 TIME_WAIT。如果过多,可能导致 socket 资源耗尽,无法正常提供服务。

也就是说,TIME_WAIT、CLOSE_WAIT 不可能出现在一台主机的一个 TCP 连接中,他要么是主动关闭的一方,要么是被动关闭的一方

主动关闭的一方的状态变化过程是 主动关闭 -> FIN_WAIT_1 -> FIN_WAIT_2 -> TIME_WAIT -> CLOSED

被动关闭的一方的状态变化过程是 被动关闭 -> CLOSE_WAIT -> LAST_ACK -> CLOSED

Linux 服务器出现大量的 CLOSE_WAIT 后,socket 资源会被耗尽。因为 Linux 分配给一个用户的文件句柄是有限的,而 TIME_WAIT 和 CLOSE_WAIT 两种状态如果一直被保持,则文件句柄也就不能 close,导致句柄资源达到上线,接着就会出现大量 Too Many Open Files 错误。

如果出现大量 CLOSE_WAIT,首先需要考虑被动关闭方的程序是否有 BUG,是否有 socket 泄露(遗漏 close())。如果别的机器上能够正常访问,TCP 正常连接,那么就不是代码问题,那么就要关注网络问题,是不是因为主动关闭方的 ACK 号(第 3 步)因为网络问题无法发送到被关闭方。导致被关闭方一直 CLOSE_WAIT/LAST_ACK。

查看当前系统中的 tcp socket 状态信息并统计:

netstat -anp | grep TIME_WAIT  | wc -l

netstat -anp | grep CLOSE_WAIT | wc -l

处理方法

CLOSE_WAIT:把占用的线程 kill 掉即可,如果是 TIME_WAIT,过一段时间,就会自己释放。