美文网首页
close_wait处理

close_wait处理

作者: 星夜兼程工作笔记 | 来源:发表于2019-08-27 22:17 被阅读0次

    首先从服务器端快速解决:修改linux内核net.ipv4.tcp_tw_recycle 和 net.ipv4.tcp_timestamps 为 0,sysctl -p使之生效。

    一、“多半是程序的原因”?这个还是交给程序猿吧

    struct linger lingerBuffer;

    lingerBuffer.l_onoff=1;//nonzero means enable Linger function.

    lingerBuffer.l_linger=0;// timeout must set to zero.

    setsockopt(fd,SOL_SOCKET,SO_LINGER,&lingerBuffer,sizeof(lingerBuffer));

    另外,设置SO_reuseaddr。

    二、linux 下 CLOSE_WAIT过多的解决方法

    情景描述:系统产生大量“Too many open files”

    原因分析:在服务器与客户端通信过程中,因服务器发生了socket未关导致的closed_wait发生,致使监听port打开的句柄数到了1024个,且均处于close_wait的状态,最终造成配置的port被占满出现“Too many open files”,无法再进行通信。

    close_wait状态出现的原因是被动关闭方未关闭socket造成

    解决办法:有两种措施可行

    一、解决:

    原因是因为调用ServerSocket类的accept()方法和Socket输入流的read()方法时会引起线程阻塞,所以应该用setSoTimeout()方法设置超时(缺省的设置是0,即超时永远不会发生);超时的判断是累计式的,一次设置后,每次调用引起的阻塞时间都从该值中扣除,直至另一次超时设置或有超时异常抛出。

    比如,某种服务需要三次调用read(),超时设置为1分钟,那么如果某次服务三次read()调用的总时间超过1分钟就会有异常抛出,如果要在同一个Socket上反复进行这种服务,就要在每次服务之前设置一次超时。

    二、规避:

    调整系统参数,包括句柄相关参数和TCP/IP的参数;

    注意:

    /proc/sys/fs/file-max 是整个系统可以打开的文件数的限制,由sysctl.conf控制;

    ulimit修改的是当前shell和它的子进程可以打开的文件数的限制,由limits.conf控制;

    lsof是列出系统所占用的资源,但是这些资源不一定会占用打开文件号的;比如:共享内存,信号量,消息队列,内存映射等,虽然占用了这些资源,但不占用打开文件号;

    因此,需要调整的是当前用户的子进程打开的文件数的限制,即limits.conf文件的配置;

    如果cat /proc/sys/fs/file-max值为65536或甚至更大,不需要修改该值;

    若ulimit -a ;其open files参数的值小于4096(默认是1024), 则采用如下方法修改open files参数值为8192;方法如下:

    1.使用root登陆,修改文件/etc/security/limits.conf

    vim /etc/security/limits.conf

    添加

    xxx - nofile 8192

    xxx 是一个用户,如果是想所有用户生效的话换成 * ,设置的数值与硬件配置有关,别设置太大了。

    #<domain>    <type>  <item>      <value>

    *        soft    nofile    8192

    *        hard    nofile    8192

    #所有的用户每个进程可以使用8192个文件描述符。

    2.使这些限制生效

    确定文件/etc/pam.d/login 和/etc/pam.d/sshd包含如下行:

    session required pam_limits.so

    然后用户重新登陆一下即可生效。

    3. 在bash下可以使用ulimit -a 参看是否已经修改:

    一、 修改方法:(暂时生效,重新启动服务器后,会还原成默认值)

    sysctl -w net.ipv4.tcp_keepalive_time=600 

    sysctl -w net.ipv4.tcp_keepalive_probes=2

    sysctl -w net.ipv4.tcp_keepalive_intvl=2

    注意:Linux的内核参数调整的是否合理要注意观察,看业务高峰时候效果如何。

    二、 若做如上修改后,可起作用;则做如下修改以便永久生效。

    vi /etc/sysctl.conf

    若配置文件中不存在如下信息,则添加:

    net.ipv4.tcp_keepalive_time = 1800

    net.ipv4.tcp_keepalive_probes = 3

    net.ipv4.tcp_keepalive_intvl = 15

    编辑完 /etc/sysctl.conf,要重启network 才会生效

    /etc/rc.d/init.d/network restart

    然后,执行sysctl命令使修改生效,基本上就算完成了。

    ------------------------------------------------------------

    修改原因:

    当客户端因为某种原因先于服务端发出了FIN信号,就会导致服务端被动关闭,若服务端不主动关闭socket发FIN给Client,此时服务端Socket会处于CLOSE_WAIT状态(而不是LAST_ACK状态)。通常来说,一个CLOSE_WAIT会维持至少2个小时的时间(系统默认超时时间的是7200秒,也就是2小时)。如果服务端程序因某个原因导致系统造成一堆CLOSE_WAIT消耗资源,那么通常是等不到释放那一刻,系统就已崩溃。因此,解决这个问题的方法还可以通过修改TCP/IP的参数来缩短这个时间,于是修改tcp_keepalive_*系列参数:

    tcp_keepalive_time:

    /proc/sys/net/ipv4/tcp_keepalive_time

    INTEGER,默认值是7200(2小时)

    当keepalive打开的情况下,TCP发送keepalive消息的频率。建议修改值为1800秒。

    tcp_keepalive_probes:INTEGER

    /proc/sys/net/ipv4/tcp_keepalive_probes

    INTEGER,默认值是9

    TCP发送keepalive探测以确定该连接已经断开的次数。(注意:保持连接仅在SO_KEEPALIVE套接字选项被打开是才发送.次数默认不需要修改,当然根据情形也可以适当地缩短此值.设置为5比较合适)

    tcp_keepalive_intvl:INTEGER

    /proc/sys/net/ipv4/tcp_keepalive_intvl

    INTEGER,默认值为75

    当探测没有确认时,重新发送探测的频度。探测消息发送的频率(在认定连接失效之前,发送多少个TCP的keepalive探测包)。乘以tcp_keepalive_probes就得到对于从开始探测以来没有响应的连接杀除的时间。默认值为75秒,也就是没有活动的连接将在大约11分钟以后将被丢弃。(对于普通应用来说,这个值有一些偏大,可以根据需要改小.特别是web类服务器需要改小该值,15是个比较合适的值)

    1. 系统不再出现“Too many open files”报错现象。

    2. 处于TIME_WAIT状态的sockets不会激长。

    在 Linux 上可用以下语句看了一下服务器的TCP状态(连接状态数量统计):

    netstat -n| awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

    办法三:

    这两天发现数据库的cpu使用率一直居高不下,服务器负载也一直很高

    在mysql里show processlist发现连接数也不多

    也没有锁表现象,可资源使用一直很高

    查了下连接不得了了啊

    netstat -anl|grep :3306

    总连接数有几百,其中有大量的CLOSE_WAIT状态的连接

    看了下数据库的连接超时设置

    set global wait_timeout=120

    再来改一下/etc/sysctl.conf,在最后加入

    net.ipv4.tcp_keepalive_time = 30

    net.ipv4.tcp_keepalive_probes = 2

    net.ipv4.tcp_keepalive_intvl = 2

    使用sysctl -p使配置生效

    而会发现会出现大量的TIME_WAIT的连接 还要再修改下linux的/etc/sysctl.conf配置

    在最后加入

    net.ipv4.tcp_fin_timeout = 30

    net.ipv4.tcp_keepalive_time = 1200

    net.ipv4.tcp_syncookies = 1

    net.ipv4.tcp_tw_reuse = 1

    net.ipv4.tcp_tw_recycle = 1

    net.ipv4.ip_local_port_range = 1024 65000

    net.ipv4.tcp_max_syn_backlog = 8192

    net.ipv4.tcp_max_tw_buckets = 5000

    net.ipv4.route.gc_timeout = 100

    net.ipv4.tcp_syn_retries = 1

    net.ipv4.tcp_synack_retries = 1

    说明:

    net.ipv4.tcp_syncookies = 1

    表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;

    net.ipv4.tcp_tw_reuse = 1

    表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;

    net.ipv4.tcp_tw_recycle = 1

    表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。

    net.ipv4.tcp_fin_timeout = 30

    表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。

    net.ipv4.tcp_keepalive_time = 1200

    表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。

    net.ipv4.ip_local_port_range = 1024 65000

    表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。

    net.ipv4.tcp_max_syn_backlog = 8192

    表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。

    net.ipv4.tcp_max_tw_buckets = 5000

    表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。

    net.ipv4.route.gc_timeout = 100

    路由缓存刷新频率, 当一个路由失败后多长时间跳到另一个默认是300

    net.ipv4.tcp_syn_retries = 1

    对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右。

    现在再来看下连接信息:

    netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

    相关文章

      网友评论

          本文标题:close_wait处理

          本文链接:https://www.haomeiwen.com/subject/rtzyectx.html