【背景说明】前端
在7层负载均衡上,查询网络状态发现timewait太多,因而开始准备优化事宜python
总体的拓扑结构,前面是lvs作dr模式的4层负载均衡,后端使用(nginx、or haproxy)作7层负载均衡nginx
【优化效果】后端
修改前,创建链接的有29个,timewait的就达到了900个,以下图所示centos
修改后,创建链接的有32个,timewait的从900下降到了49个,以下图所示安全
【具体优化方案】服务器
注意:前端使用nat时,不适用本策略。详细“方案详细介绍”会说明网络
修改7层负载所在机器,/etc/sysctl.conf负载均衡
net.ipv4.tcp_tw_reuse = 1less
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_fin_timeout = 20
保存后sysctl -p生效
【方案详细介绍】
net.ipv4.tcp_tw_reuse=1
#表示开启重用。容许将TIME-WAIT sockets从新用于新的TCP链接,默认为0,表示关闭;该文件表示是否容许从新应用处于TIME-WAIT状态的socket用于新的TCP链接(这个对快速重启动某些服务,而启动后提示端口已经被使用的情形很是有帮助)
net.ipv4.tcp_tw_recycle=1
#表示开启TCP链接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_timestamps 开启时,net.ipv4.tcp_tw_recycle开启才能生效,缘由能够参考如下代码
if(tcp_death_row.sysctl_tw_recycle&&tp->rx_opt.ts_recent_stamp)recycle_ok=icsk->icsk_af_ops->remember_stamp(sk); if(recycle_ok){ tw->tw_timeout=rto; } else{tw->tw_timeout=TCP_TIMEWAIT_LEN; if(state==TCP_TIME_WAIT) timeo=TCP_TIMEWAIT_LEN; }
若是服务器身处NAT环境,安全起见,一般要禁止tcp_tw_recycle,若是nat下,开启了 tcp_tw_recycle,可能会致使部分用户没法链接服务器的状况:在nat模式下(服务器通常会用到dnat,用户通常会用到snat),nat 设备(or服务器)会修改目的ip和源ip,以屏蔽内部信息。试想不少用户snat出来,经过dnat访问网站,在dnat这层,时而会产生时间戳错乱的 问题,那么基于tcp的时间戳的tcp_tw_recycle,就会出错。具体可参考
fc1323的扩展的说明
RFC1323TCPExtensionsforHighPerformanceMay1992 discardedwhenaconnectionisclosed. AnadditionalmechanismcouldbeaddedtotheTCP,aper-host cacheofthelasttimestampreceivedfromanyconnection. ThisvaluecouldthenbeusedinthePAWSmechanismtoreject oldduplicatesegmentsfromearlierincarnationsofthe connection,ifthetimestampclockcanbeguaranteedtohave tickedatleastoncesincetheoldconnectionwasopen.This wouldrequirethattheTIME-WAITdelayplustheRTTtogether mustbeatleastonetickofthesender'stimestampclock. SuchanextensionisnotpartoftheproposalofthisRFC. Notethatthisisavariantonthemechanismproposedby Garlick,Rom,andPostel[Garlick77],whichrequiredeach hosttomaintainconnectionrecordscontainingthehighest sequencenumbersoneveryconnection.Usingtimestamps instead,itisonlynecessarytokeeponequantityperremote host,regardlessofthenumberofsimultaneousconnectionsto thathost.
大体意思为:tcp会记录每一个链接的时间戳,若是后续时间戳比以前记录的时间戳小,就会认为这是错误的链接,拒绝这 个链接。若是tcp_tw_recycle开启,那么这种规则就会被激活(那样才能快速回收链接)。因此在lvs使用nat的状况下,用户请求到 lvs,LVS会修改地址数据后将请求转发给后端服务器,但不会修改时间戳(由于nat的机制就是只修改源地址和目的地址)。在后端服务器看来,请求的源 地址永远都是LVS的地址,而且端口复用,本来不一样客户端的请求通过LVS的转发,就可能会被认为是同一个链接,加之不一样客户端的时间可能不一致,因此就 会出现时间戳错乱的现象,因而后面的数据包就被丢弃了,具体的表现一般是是客户端明明发送的SYN,但服务端就是不响应ACK,还能够经过下面命令来确认 数据包不断被丢弃的现象。就会出现部分用户能链接服务器,部分用户不能链接服务器的状况。
但在LVS使用用dr模式状况下,lvs只会修改mac和ip地址的映射关系,后端服务器看到的仍是不通的用户ip,因此激活这一规则,也不会有问题。咱们这里能使用这个策略,最大的缘由也是在这里。
net.ipv4.tcp_timestamps=1
#表示开启TCP链接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout = 15;这个参数是用来设置保持在FIN_WAIT_2状态的时间。tcp4此挥手,正常的处理流程就是在FIN_WAIT_2状况下接收到FIN进入到 TIME_WAIT的状况,tcp_fin_timeout参数对处于TIME_WAIT状态的时间没有任何影响。可是若是这个参数设的比较小,会缩短从 FIN_WAIT_2到TIME_WAIT的时间,从而使链接更早地进入TIME_WAIT状态。状态开始的早,等待相同的时间,结束的也早,客观上也加 速了TIME_WAIT状态套接字的清理速度。
tcp链接的断开,可参考如下状态机:
【补充说明】
若是变动后运行命令netstat -s|grep timestamp
发现packets rejects in established connections because of timestamp
数值增长的很快,你可能得回滚这个变动了:说明使用snat访问你网站的人不少
因 为:虽然服务器端没有使用nat,可是客户端使用snat的状况不少,若是后发现packets rejects in established connections because of timestamp增加很快,建议将这个方案回滚。那时,可以使用修改net.ipv4.tcp_max_tw_buckets(centos默认彷佛是 262144)可调整至100000。其实也说明,timeout数量不大的时候,其实能够不用调整tcp_tw_recycle参数(风险很大)。
【总结】
一个小小的变动,背后涉及的知识是异常多的,因此须要
一、不能随意找个方案就使用,须要深刻理解。就像说这个A药能够治疗B症状,可是本质是A药能够治疗C病因状况下得B症状,须要把病因搞清楚了再吃药。就算侥幸治疗好了,也不能永远都是报这种侥幸心理。
二、对于内核参数调整,须要对每一个参数都了解以后再行动,不然可能会有悲剧。
三、变动的时候,须要有一个灰度过程,须要观察一段时间后,再大面积修改。