一、背景html
团队有2台API服务,使用Resin4布署的web服务。刚上线调用方很是少,跑了几个月后,程序正常得很。linux
可是因为业务的发展,此API要给多个高并发的应用调用,级别在300w/天左右,瞬间请求可去到100+/s。web
本身看服务,其实服务执行状况还好,虽然请求量高了些,可是程序的成功率很高,CPU有波动,可是算正常。bash
但是后来,调用方运行一段时间后,说有1/3的请求都被拒绝或者超时了。因而在想是否是resin4可支撑的线程数过小。服务器
二、第一次调优cookie
因而修改了resin.properties里的线程池的大小:网络
# Throttle the number of active threads for a port port_thread_max : 1024 accept_thread_max : 1024 accept_thread_min : 32
port_thread_max: 每一个端口最多能够有的活跃线程数,避免系统负载压力过大。并发
可是观察了一段时间后,效率不明显,仍是有拒绝。负载均衡
三、第二次调优socket
就在昨天,发现两台服务一直在告警,说服务不可达,其实就是超长时间无响应。
无心中发现2台服务器的负载状况不均衡,一台基本没有请求到,一台不少请求。
这个其实跟上层的负载均衡有比较大关系。
可是经过查看系统状况,发现进程中存在大量的TIME_WAIT。
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 23456 FIN_WAIT1 3 FIN_WAIT2 26 ESTABLISHED 185 SYN_RECV 2 LAST_ACK 1
通过查看如下两篇文章:
http://kerry.blog.51cto.com/172631/105233/
http://blog.chinaunix.net/uid-24517549-id-4048652.html
其中有说到:
根据TCP协议定义的3次握手断开链接规定,发起socket主动关闭的一方 socket将进入TIME_WAIT状态,TIME_WAIT状态将持续2个MSL(Max Segment Lifetime),在Windows下默认为4分钟,即240秒,TIME_WAIT状态下的socket不能被回收使用. 具体现象是对于一个处理大量短链接的服务器,若是是由服务器主动关闭客户端的链接,将致使服务器端存在大量的处于TIME_WAIT状态的socket, 甚至比处于Established状态下的socket多的多,严重影响服务器的处理能力,甚至耗尽可用的socket,中止服务.
因而参考修改:
发现系统存在大量TIME_WAIT状态的链接,经过调整内核参数解决,
vi /etc/sysctl.conf
编辑文件,加入如下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
而后执行
/sbin/sysctl -p
让参数生效。
状况立刻有好转,TIME_WAIT迅速降低,Established开始上升并稳定。
---2017年更新---
打开了端口回收,会致使大量链接失败。建议改成如下:
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_timestamps = 1
把这三行加进去/etc/sysctl.conf,而后sysctl -p
而后把linux默认的可用端口号调大。由于默认的端口号为:
#sysctl -a|grep ip_local_port_range
net.ipv4.ip_local_port_range = 32768 61000
可修改 为:
net.ipv4.ip_local_port_range = 1024 65535
四、可选优化
链接数自己就不少,咱们能够再优化一下TCP/IP的可以使用端口范围,进一步提高服务器的并发能力。依然是往上面的参数文件中,加入下面这些配置:
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.ip_local_port_range = 10000 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000这几个参数,建议只在流量很是大的服务器上开启,会有显著的效果。通常的流量小的服务器上,没有必要去设置这几个参数。这几个参数的含义以下:
net.ipv4.tcp_keepalive_time = 1200 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改成20分钟。
net.ipv4.ip_local_port_range = 10000 65000 表示用于向外链接的端口范围。缺省状况下很小:32768到61000,改成10000到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拖死。
五、总结:
因此要多角度考虑,一个软件的不足,不仅是考虑其自己的问题,还要考虑所处的系统环境。