[20200312]不要设置net.ipv4.tcp_tw_recycle=1.txt
--//昨天认真看了2篇blog:
https://vincent.bernat.ch/en/blog/2014-tcp-time-wait-state-linux
--//中文翻译:
http://www.cnxct.com/coping-with-the-tcp-time_wait-state-on-busy-linux-servers-in-chinese-and-dont-enable-tcp_tw_recycle/
--//里面提到不要设置net.ipv4.tcp_tw_recycle=1。TIME_WAIT状态问题不是太严重,可以完全不理会它。
--//我仔细阅读,说真的许多一些细节还不是很理解。我开始接触主要是不理解生产系统rac环境为什么这么多state=TIME_WAIT.
--//现在看来自己纯粹是画蛇添足,浪费时间,不过自己感觉还是学到许多东西.
--//现在我大概知道原因,做一些总结:
1.实际上对于正常数据库应用,正常退出应用程序,实际上state=TIME_WAIT发生在客户端,这也是我开始的困惑。服务端不应该这个多
state=TIME_WAIT。我的问题实际上由此展开^_^.
https://vincent.bernat.ch/en/blog/2014-tcp-time-wait-state-linux
TCP state diagram
Only the end closing the connection first will reach the TIME-WAIT state. The other end will follow a path which usually
permits to quickly get rid of the connection.
--//只有先关闭连接的结束才会达到TIME-WAIT状态.. 另一端将沿着通常允许快速摆脱连接。
2.我们使用dblink短连接很多,这时服务端实际上变成客户端,导致state=TIME_WAIT多。
3.exadata 出厂设置 net.ipv4.tcp_timestamps = 0,即使我设置net.ipv4.tcp_tw_recycle=1也无效,毫无作用,这也是我在测试中遇
到的第二个困惑。我想oracle这样做可能有它的道理, 不会使用特殊的方式规避其它dba设置net.ipv4.tcp_tw_recycle=1的问题。
--//exadate 的 /etc/sysctl.conf设置,不知道前面# 12650500 ,oracle内部表示什么?
# 12650500
net.ipv4.tcp_timestamps = 0
--//再次提醒建议不要设置net.ipv4.tcp_tw_recycle=1 解决大量state=TIME_WAIT问题。
4.还有1个原因导致服务端state=TIME_WAIT增多,就是客户端连接RAC数据库使用scan ip,会跳转到vip ip,这样一旦大量用户以这种方式
登录,就是在服务端产生大量的state=TIME_WAIT连接。
5.还有前台客户端基本都是XP机器。我的测试MS关于tcp_timestamps缺省设置是关闭的,至少在windows 7,windows 2003服务器版下,XP
我不知道。
这样即使服务端设置 net.ipv4.tcp_timestamps = 1 和 net.ipv4.tcp_tw_recycle=1 依旧在服务端生产大量的state=TIME_WAIT.
不过linux机器缺省设置都是net.ipv4.tcp_timestamps = 1。
--//再次提醒建议不要设置net.ipv4.tcp_tw_recycle=1 解决大量state=TIME_WAIT问题。
--//注:我在这里测试时又犯了一个错误,以为跨网段的机器不能快速回收TIME_WAIT,实际上是我的测试机器windows7的
--//tcp_timestamps缺省设置是关闭的.
6.有一个可行的方法减少大量state=TIME_WAIT连接,就是在一些中间件服务器可以不要使用scan ip连接数据库,采用老的vip ip就可以
减少这样的情况。改动涉及中间件服务器,影响不大,这是比较可行成本最低的改进方法,仅仅对rac环境有效.
--//话又反活来讲,如果不是rac环境,可能就看不到大量的state=TIME_WAIT状态.
7.如果网络链接通过公网或者NAT转换,肯定不能设置net.ipv4.tcp_tw_recycle=1. 由于我们一些应用通过公网,当我设置
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_timestamps=1
--//确实有少量的客户端(实际上也就2台)无法连接服务器的情况,甚至内网的机器也出现一台,我不知道为什么。最终还原原来设置
net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_timestamps=0
8.内存 CPU 资源消耗很少。参考链接的测试:https://vincent.bernat.ch/en/blog/2014-tcp-time-wait-state-linux
9.state=TIME_WAIT对应用影响很小,4元素组成一个连接,oracle 建议内核参数设置net.ipv4.ip_local_port_range = 1024 65000
支持端口数量达到64000,这样如果不达到每秒60000/60 = 1000 个/连接,基本影响可以忽略。
我感觉不能达到这个数量,至少我自己没见过。我们数据库高峰也就是200个/每秒连接。
10.TIME_WAIT状态的消失时间在linux下写死的,在net/tcp.h头文件里面的,许多链接提示修改net.ipv4.tcp_fin_timeout是错误的:
--//除非修改头文件内容,重新编译内核!!
#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
* state, about 60 seconds */
#define TCP_FIN_TIMEOUT TCP_TIMEWAIT_LEN
/* BSD style FIN_WAIT2 deadlock breaker.
* It used to be 3min, new value is 60sec,
* to combine FIN-WAIT-2 timeout with
* TIME-WAIT timer.
*/
11.windows下可以修改TIME_WAIT状态的消失时间:
--//在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters上添加一个DWORD类型的值TcpTimedWaitDelay,值
--//就是秒数,最小30秒,不能低于该值.注要重启机器才能生效:
--//timewait.reg
REGEDIT4
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters]
"TcpTimedWaitDelay"=dword:0000001e
12.windows下设置tcp_timestamps:
--//按照https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc938205(v=technet.10)?redirectedfrom=MSDN
Tcp1323Opts
--//注:1323 应该是关联RFC 1323文档.
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data type Range Default value
------------------------------------------
REG_DWORD 0 | 1 | 2 | 3 3
Value Meaning
0 (00) Timestamps and window scaling are disabled.
1 (01) Window scaling is enabled.
2 (10) Timestamps are enabled.
3 (11) Timestamps and window scaling are enabled.
--//按照介绍MS缺省应该是打开tcp_timestamps的。不过我发现在windows 7,windows 2003下不是这样。修改为2或者3.我仅仅测试修改3
--//的情况.
REGEDIT4
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters]
"Tcp1323Opts"=hex:03
13.最后简单讲一下测试方法,使用tnsping server_ip count > /dev/null,这样比较简单快捷,这时state=TIME_WAIT出现在服务端,使用
netstat -ntop 或者ss -nto 观察.
# seq 10000 | xargs -IQ bash -c "ss -tano state time-wait | ts.awk ; sleep 1"
or
# seq 10000 | xargs -IQ bash -c "netstat -nto | grep TIME-WAIT | ts.awk ; sleep 1"
$ cat $(which ts.awk)
# /bin/bash
gawk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }'
在服务端net.ipv4.tcp_tw_recycle=1,net.ipv4.tcp_timestamps=1,客户端net.ipv4.tcp_timestamps=1的情况下服务端出现TIME_WAIT很快消失.
在服务端net.ipv4.tcp_tw_recycle=1,net.ipv4.tcp_timestamps=1,客户端net.ipv4.tcp_timestamps=0的情况下服务端出现TIME_WAIT等60秒消失.
在服务端net.ipv4.tcp_tw_recycle=1,net.ipv4.tcp_timestamps=0, 服务端出现TIME_WAIT等60秒消失.
在服务端net.ipv4.tcp_tw_recycle=0,net.ipv4.tcp_timestamps=N(N=1,0) 服务端出现TIME_WAIT等60秒消失.
--//大家可以自行测试.测试结果就不贴上来了,有点繁琐.
--//从这里也看出如果大量的客户端是windows,没有打开tcp_timestamp,在服务端设置
--//net.ipv4.tcp_tw_recycle=1,net.ipv4.tcp_timestamps=1也一样毫无用处.
14.演示一个服务端产生大量TIME_WAIT的例子:
--//还是另外写一篇,不然写的又太长了.
--//最后再次提醒建议不要设置net.ipv4.tcp_tw_recycle=1来解决大量state=TIME_WAIT问题,重要的问题说三遍,国内大量的链接这样
--//做可能会导致一些网络故障非常难查,除非应用都是非常纯的内网环境里面。