一,在系统执行命令时报错error: too many open files
在linux中一切皆文件,例如监听的端口,设备,文件,进程等,都需要占用一个文件描述符(fd)。故在linux系统中最大打开文件描述符数open files,就很容易在大并发请求的系统上成为瓶颈。
调整的方法:
# echo "ulimit -n 1000000" >> /etc/profile
二,SYN Flood攻击
SYN Flood是当前最流行的DoS(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,常用假冒的IP或IP号段发来海量的请求连接的第一个握手包(SYN包),被攻击服务器回应第二个握手包(SYN+ACK包),因为对方是假冒IP,对方永远收不到包且不会回应第三个握手包。导致被攻击服务器保持大量SYN_RECV状态的“半连接”,并且会重试默认5次回应第二个握手包,塞满TCP等待连接队列,资源耗尽(CPU满负荷或内存不足),让正常的业务请求连接不进来。
我们看到业务曲线大跌时,检查机器和DNS,发现只是对外的web机响应慢、CPU负载高、ssh登陆慢甚至有些机器登陆不上,检查系统syslog,会有类此如下的信息:
# tail -f /var/log/messages
Apr 18 11:21:56 web5 kernel: possible SYN flooding on port 80. Sending cookies.
检查连接数增多,并且SYN_RECV 连接特别多:
# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 16855
CLOSE_WAIT 21
SYN_SENT 99
FIN_WAIT1 229
FIN_WAIT2 113
ESTABLISHED 8358
SYN_RECV 48965
CLOSING 3
LAST_ACK 313
我们可以通过调优kernel来缓解攻击:
1)net.ipv4.tcp_synack_retries = 0
这个比较重要,表示回应第二个握手包(SYN+ACK包)给客户端IP后,如果收不到第三次握手包(ACK包)后,进行0次重试,加快回收“半连接”。
2)net.ipv4.tcp_max_syn_backlog=16384
进入SYN包的最大请求队列长度,默认1024。对重负载服务器,增加该值显然有好处。
3)net.ipv4.tcp_syncookies = 1
打开syn cookie功能,攻击当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN,默认为0,表示关闭。
如果,调节kernel仍不能减轻syn flood攻击的话,直接用nginx或iptables封有嫌疑的ip。
三,系统socket TIME_WAIT过多
当socket连接由client端主动关闭后,socket连接最后会处于TIME_WAIT状态一段时间。一般情况下,这段时间为
2MSL(MSL:tcp报文段最大生存时间,他是任何报文段被丢弃前在网络内的最大时间,这样做也是为了让那些传输慢的报文段能被成功接收)。RFC 793[ Postel 1981c]指出MSL为2分钟,但是现实中常用值为30s或1min或2min。
当系统中有大量socket TIME_WAIT状态时,导致占用过多系统端口(而一个端口就是fd)。例如我们有个服务监听的端口为8012,重启的时候经常会提示端口被占用。
通过查看/proc/sys/net/ipv4/ip_local_port_range可以知道设置的Linux内核自动分配端口的端口范围:
# cat /proc/sys/net/ipv4/ip_local_port_range
1025 65535
减少方法:
1)net.ipv4.tcp_tw_reuse = 1
表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
2)net.ipv4.tcp_tw_recycle = 1
表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
3)net.ipv4.tcp_fin_timeout = 30
#表示如果套接字由本端主动要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
四,使用ip_conntrack模块导致系统丢包
kernel 用 ip_conntrack 模块来记录 iptables 网络包的状态,并把每条记录保存到 table 里(这个 table 在内存里,可以通过/proc/net/ip_conntrack 查看当前已经记录的总数),如果网络状况繁忙,比如高连接,高并发连接等会导致逐步占用这个 table 可用空间,一般这个 table 很大不容易占满并且可以自己清理,table 的记录会一直呆在 table 里占用空间直到源 IP 发一个 RST 包,但是如果出现被攻击、错误的网络配置、有问题的路由/路由器、有问题的网卡等情况的时候,就会导致源 IP 发的这个 RST 包收不到,这样就积累在 table 里,越积累越多直到占满。无论,哪种情况导致table变满,满了以后就会丢包,出现外部无法连接服务器的情况。内核会报如下错误信息:kernel: ip_conntrack: table full, dropping packet。
在/proc/net/ip_conntrack中,每一个跟踪连接表会占用304字节的内核存储空间,跟踪连接越多,越占用系统内存:
# cat /var/log/messages|grep conn
Nov 28 13:18:20 yd_82_231 kernel: ip_conntrack version 2.4 (8192 buckets, 65536 max) - 304 bytes per conntrack
调整方法:
1)net.ipv4.netfilter.ip_conntrack_max = 655360
增大跟踪的最大条数
2)net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 10800
减少跟踪连接的最大有效时间
五,server连接数高一般调整的tcp相关参数
1)/proc/sys/net/ipv4/tcp_mem
# cat /proc/sys/net/ipv4/tcp_mem
786432 2097152 3145728
确定 TCP 栈应该如何反映内存使用;每个值的单位都是内存页(通常是 4KB)。第一个值是内存使用的下限。第二个值是内存压力模式开始对缓冲区使用应用压力的上限。第三个值是内存上限。在这个层次上可以将报文丢弃,从而减少对内存的使用。对于较大的 BDP 可以增大这些值(但是要记住,其单位是内存页,而不是字节)。
2)/proc/sys/net/ipv4/tcp_wmem
# cat /proc/sys/net/ipv4/tcp_wmem
4096 65536 8388608
为自动调优定义每个 socket 使用的内存。第一个值是为 socket 的发送缓冲区分配的最少字节数。第二个值是默认值(该值会被 wmem_default 覆盖),缓冲区在系统负载不重的情况下可以增长到这个值。第三个值是发送缓冲区空间的最大字节数(该值会被 wmem_max 覆盖)。
3)/proc/sys/net/ipv4/tcp_rmem
# cat /proc/sys/net/ipv4/tcp_rmem
4096 87380 8388608
与 tcp_wmem 类似,不过它表示的是为自动调优所使用的接收缓冲区的值。