从这个展示的通讯情况可以看到,80端口下起了两个LISTEN监听进程,分别是在root用户下和nobody用户下,并且可以看到ip为192.168.1.100的电脑和80端口进行了TCP通讯链接,TCP通讯链接的状态为
ESTABLISHED,并且链接时占用了服务器上的53151和53152 这两个端口。
TCP通讯链接是在做性能测试时经常需要关注的,尤其是在高并发的情况下如何优化TCP链接数和TCP链接的快速释放,是性能调优的一个关注点。链接的常用状态如下
状态
解释
LISTEN
监听状态,这个一般应用程序启动时,会启动监听,比如nginx程序启动后,就会产生监听进程,一般的时候,监听进程的端口都是可以自己进行设置,以防止端口冲突
ESTABLISHED
链接已经正常建立,表示客户端和服务端正在通讯中。
CLOSE_WAIT
客户端主动关闭连接或者网络异常导致连接中断,此时这次链接下服务端的状态会变成CLOSE_WAIT,需要服务端来主动进行关闭该链接。
TIME_WAIT
服务端主动断开链接,收到客户端确认后链接状态变为TIME_WAIT,但是服务端并不会马上彻底关闭该链接,只是修改了状态。TCP协议规定TIME_WAIT状态会一直持续2MSL的时间才会彻底关闭,以防止之前链接中的网络数据包因为网络延迟等原因延迟出现。处于TIME_WAIT状态的连接占用的资源不会被内核释放,所以性能测试中如果服务端出现了大量的TIME_WAIT状态的链接就需要分析原因了,一般不建议服务端主动去断开链接。
SYN_SENT
表示请求正在链接中,当客户端要访问服务器上的服务时,一般都需要发送一个同步信号给服务端的端口,在此时链接的状态就为SYN_SENT,一般SYN_SENT状态的时间都是非常短,除非是在非常高的并发调用下,不然一般SYN_SENT状态的链接都非常少。
不管是什么状态下的TCP链接,都会占用服务器的大量资源,而且每个链接都会占用一个端口,Linux服务器的TCP和UDP的端口总数是有限制的(0-65535),超过这个范围就没有端口可以用了,程序会无法启动,链接也会无法进行。所以如果服务端出现了大量的CLOSE_WAIT和TIME_WAIT的链接时,就需要去及时去查找原因和进行优化。CLOSE_WAIT状态一般大部分的时候,都是自己写的代码或者程序出现了明显的问题造成。
针对如果出现了大量的TIME_WAIT状态的链接,可以从服务器端进行一些优化以让服务器快速的释放TIME_WAIT状态的链接占用的资源。优化的方式如下
使用vim /etc/sysctl.conf来编辑sysctl.conf文件以优化Linux操作系统的文件内核参数设置,加入如下配置:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time=600
net.ipv4.tcp_max_tw_buckets = 5000
fs.file-max = 900000
net.ipv4.tcp_max_syn_backlog = 2000
net.core.somaxconn = 2048
net.ipv4.tcp_synack_retries = 1
net.ipv4.ip_local_port_range =1000 65535
net.core.rmem_max = 2187154
net.core.wmem_max = 2187154
net.core.rmem_default = 250000
net.core.wmem_default = 250000
然后执行sysctl –p命令可以内核让参数立即生效,这种调优一般在nginx、apache 这种web服务器上会经常用到。
net.ipv4.tcp_syncookies = 1 表示开启syn cookies,当出现syn等待队列溢出时启用cookies来处理,默认情况下是关闭状态。客户端向linux服务器建立TCP通讯链接时会首先发送SYN包,发送完后客户端会等待服务端回复SYN+ACK,服务器在给客户端回复SYN+ACK后,服务器端会将此时处于SYN_RECV状态的连接保存到半链接队列中以等待客户端继续发送ACK请求给服务器端直到最终链接完全建立,在出现大量的并发请求时这个半链接队列中可能会缓存了大量的SYN_RECV状态的链接从而导致队列溢出,队列的长度可以通过内核参数net.ipv4.tcp_max_syn_backlog进行设置,在开启cookies后服务端就不需要将SYN_RECV状态的半状态链接保存到队列中,而是在回复SYN+ACK时将链接信息保存到ISN中返回给客户端,当客户端进行ACK请求时通过ISN来获取链接信息以完成最终的TCP通讯链接。
net.ipv4.tcp_tw_reuse = 1 表示开启链接重用,即允许操作系统将TIME-WAIT socket的链接重新用于新的tcp链接请求,默认为关闭状态。
net.ipv4.tcp_tw_recycle = 1 表示开启操作系统中TIME-WAIT socket链接的快速回收,默认为关闭状态。
net.ipv4.tcp_fin_timeout = 30 设置服务器主动关闭链接时,scoket链接保持等待状态的最大时间。