用户反馈maven@osc没法访问了。并且是频繁没法中止服务,因此决定花些时间,好好找下缘由。做为运维方面的菜鸟,花了一周多的时间,走了不少弯路,也学到很多东西,最后仍是找到的缘由:没有启用持久链接(persistent connetion)(我认为是,一个用户每每是一次下载不少个jar文件,而频繁的创建链接,关闭链接,访问速度慢,服务器压力也大)。感谢@化境 http://my.oschina.net/cnhuqing 和@陈绍榕 http://my.oschina.net/u/2511364 过程当中提供的帮助。html
####1. 问题就是:搜索页面加载慢、文件下载慢,而且时常中止服务。nginx
首先,查看了一下mrtg日志的80端口链接数,挺多的。apache
能够看出来,出问题的week50和week51,链接数平均有500多(后面39链接数,是解决以后的数量)tomcat
当时,猜想会不会是有人恶意请求,就去查看nginx和tomcat日志bash
####2. 接着查看nginx的日志文件了,统计日志文件中每种http status的数服务器
perl -e 'while(<>){if(/\s([2345]\d\d)\s+\d/){$status{$1}++;}} while(($key,$value)=each %status){print "$key:$value\n"}' maven.oschina.log ; wc -l maven.oschina.log
499状态的特别多,http协议中没有该状态码,这是nginx的定义的。less
ngx_string(ngx_http_error_495_page), /* 495, https certificate error / ngx_string(ngx_http_error_496_page), / 496, https no certificate / ngx_string(ngx_http_error_497_page), / 497, http to https / ngx_string(ngx_http_error_404_page), / 498, canceled / ngx_null_string, / 499, client has closed connection */ 意思是客户端已经关闭了链接。 proxy_ignore_client_abort on; http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_client_abort Determines whether the connection with a proxied server should be closed when a client closes the connection without waiting for a response. 当客户端关闭链接后,是否须要等代理服务器作了响应后,才关闭与代理服务器的链接。 默认值是off,当客户端提早关闭了链接,nginx就会记录499状态的日志。启用后,再次统计日志再也不出现499。 但仍是没有解决问题,为何用户会提早关闭链接呢,没有解决。运维
####3. 不是怀疑有人恶意请求么,那就继续统计nginx日志中请求数最多的50个ip,命令以下:socket
awk '{print $1}' ./maven.oschina.log | sort | uniq -c | sort -n -k 1 -r | head -n 50
统计全部的日志,请求数量最多的50个ip tail -n 2000 ./maven.oschina.log |awk '{print $1}' | sort | uniq -c | sort -n -k 1 -r | head -n 10
统计最后2000行日志,请求数量最多的10个ip 简单粗暴,将请求不少的一些ip,查看下请求内容,重复特别多的直接block掉,@陈绍榕 还帮忙谢了一个简单粗暴的脚本,最新请求的last_num_lines行日志中,请求数量超过max_requires_num阀值的ip,直接block掉。这样处理后仍是没法解决问题。后来也证实这样是过于无脑粗暴。脚本以下:maven
#!/bin/bash # Author: csr # Date 2015-12-152 # Email: chenshaorong@oschina.cn # Version: v1.0 max_requires_num=200 last_num_lines=1200 now=`date` dir='/mnt/raid/nginx-logs/' if [ ! -d $dir ]; then echo -e "\033[31mDirectory no exists.\033[0m" exit 1 fi cd $dir while getopts ":m:l:h" value; do case $value in h) echo -e "\033[36mm: max requests number.\nl: last number lines.\033[0m" exit 0 ;; m) max_requires_num=$OPTARG ;; l) last_num_lines=$OPTARG ;; ?) echo -e "\033[31mInvalid arg: -h to help\033[0m" exit 2 ;; esac done for num_ip in `tail -n $last_num_lines ./maven.oschina.log |awk '{print $1}' |sort |uniq -c |sort -nr |awk '{if($1>='$max_requires_num'){print $1":"$2}}'`; do ip=${num_ip#*:} num=${num_ip%:*} #/usr/sbin/ufw insert 1 deny from $ip echo "$num $ip $now $last_num_lines $max_requires_num" >> deny_ip.txt done
####4. 统计每种链接状态的数量
netstat -n | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'
统计结果举例: FIN_WAIT2 2 CLOSING 1 SYN_RECV 1 CLOSE_WAIT 3986 TIME_WAIT 481 ESTABLISHED 2331 LAST_ACK 24 FIN_WAIT1 10
开始,我是不太清楚这些数据的正常状况下的值的,可是我仍是猜想了下,ESTABLISHED(创建链接的),TIME_WAIT(等待的),就冲着这个方向去了,查看创建链接数多的ip,而后“大(yu)胆(chun)”的屏蔽了这些ip。可想而知,没什么做用。
请教@化境 ,他看了数据后,说CLOSE_WAIT值是根本缘由,而致使CLOSE_WAIT值过大的缘由,应该是应用自己的问题。 由于应用升级也好,优化也好,这是一个费时费力的事情,因此仍是先从其余方面找突破口。我就去查资料,同时也找了一些运维群去请教CLOSE_WAIT的问题。 资料里面讲述了CLOSE_WAIT的生成缘由: http://blog.whyun.com/posts/socket/
当客户端主动关闭socket,就会出现大量CLOSE_WAIT;当服务器端主动关闭socket,就会出现大量TIME_WAIT。 根据找到的博客,试着修改了/etc/sysctl.conf文件:
表示开启重用。容许将TIME-WAIT sockets从新用于新的TCP链接,默认为0,表示关闭 net.ipv4.tcp_tw_reuse = 1 #表示开启TCP链接中TIME-WAIT sockets的快速回收,默认为0,表示关闭 net.ipv4.tcp_tw_recycle = 1 #表示系统同时保持TIME_WAIT的最大数量,若是超过这个数字, #TIME_WAIT将马上被清除并打印警告信息。默认为180000,改成5000。 net.ipv4.tcp_max_tw_buckets = 5000
并看不出什么效果。
####5. 而后,想会不会有机器一直链接服务器,占用不少的链接数。因此统计80端口,链接数最多的ip和链接数,命令以下:
netstat -pntu | grep :80 | awk '{print $5}' | cut -d: -f1 | awk '{++ip[$1]} END {for(i in ip) print ip[i],"\t",i}' | sort -nr|less
127.0.0.1本地链接确定没问题了。其余ip的链接数特别大的,就直接使用ufw屏蔽掉了。可是发现nginx日志中,仍是有对应ip的请求,以为是否是ufw无效啊,打算换用iptables。@陈绍榕 说已经establish的链接能够继续请求,若是断开了就没法创建链接。可是过了好久那些屏蔽掉的ip,仍是能够请求,果断抛弃ufw,换成iptables,依然屏蔽不掉,见鬼了。 后来发现,这里的链接数多的ip是maven代理的上游maven服务器的ip,那些屏蔽不掉的请求,应该是咱们的maven服务器对out的请求。屏蔽上游ip后,上游服务器没法响应maven@osc请求了,发现后,立刻清空了全部屏蔽ip。愚不可及。
####6. 最后从新捋了一遍上面的事情,以为使用持久链接,减小链接创建次数,可让请求更快。 通过几天折腾,各类尝试,仍是没有解决,已经淡然了。我就挨着看Tomcat8官方文档配置: https://tomcat.apache.org/tomcat-8.0-doc/config/http.html keepAliveTimeout 链接不关闭,保持开启的时间。 而后去nginx官网配置找了下: http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout 果真有,对应的配置。 再联想到这张图:
tomcat配置已经配置了keepAliveTimeout="120000"(单位是毫秒) nginx配置居然设置为keepalive_timeout 0;( The zero value disables keep-alive client connections。)居然没有启用。 速度改为keepalive_timeout 120s; 怀着试试看的态度,reload了nginx,哇塞,哇塞塞,除了第一次访问页面时候,有些慢,第二次,第三次查询都很是快。
最终解决的方法很是简单,可是过程是煎熬的,在小伙伴的帮助下,学到了很是多的知识。