前言:Web应用一般会部署nginx、tomcat、php等应用,使用默认的内核参数设置可以满足大部分场景,如果对内核参数进行了优化,也可以释放大量的服务器性能,尤其是在高并发的情况下。SYN状态内核参数调优大量的SYN_SENT这个是在没有收到响应的情况下主动连接服务器,也就是SYN超时,一般服务器根本不存在或者无法访问。比如我只是telnet了一个位置的IP和端口telnet172.18.11.110:90[root@testbbs]#ss-an|grepSYNSYN-SENT01172.16.196.145:55052172.18.11.110:90除了以上,还有一个是你的服务异常。比如mysql服务器挂了。web服务访问mysql数据库时,连接不上,也会出现SYN_SENT状态,但不管怎样,都是主动发起连接导致的,所以业务方案比较好net.ipv4.tcp_syn_retries=2如果新连接没有响应,内核会发送多少次SYN连接才放弃。默认值为5,Linux下默认重试次数为5次,不能大于255,重试间隔从1s开始每次加倍(因为响应还在等待第二次重试,所以实际上是从3秒开始),5次的重试间隔是3s、7s、15s、31s、63s,共63s,TCP会断开连接。统计数据的计算公式为2^(n+1)-1,因此设置越大,翻倍越多。对应内网环境,将该值修改为2比较合适。出现大量SYN_RECV和大量SYN的两种情况,可能是攻击。也可能是正常的业务请求,不管是哪种,都会占用大量的服务器资源。net.ipv4.tcp_synack_retries=2和参数net.ipv4.tcp_syn_retries一样,但是这个内核参数是控制响应SYN失败的重试次数。默认值也是5,同上改成2。调整net.ipv4.tcp_syncookies=1以启用SYNcookie。当SYN等待队列溢出时,启用cookie进行处理。什么是SYNcookie?我们知道SYN攻击是一系列伪造的带有IP源地址的SYN包,IP地址是随机选择的,不给攻击者提供任何线索。SYN攻击一直持续到服务的SYN队列已满。如果开启这个参数,SYNcookies会缓存此时TCP请求的SYN,等服务器正常的时候再处理,但是如果攻击并发量又高又大,用处不大,所以只有小SYNcookiesamountofSYNcookies可以参考:https://blog.csdn.net/chenmo1...net.ipv4.tcp_max_syn_backlog=65535指定最大可以接受SYN同步包的客户端数量,即上限的半连接。默认值为128。对于web服务,频繁的大量SYN同步包,这个值应该放大连接的状态,如果是被动关闭而不发送FIN关闭连接,那么这个状态会一直存在.当然Linux对于这种状态是有超时时间的,默认是60秒。优秀的TIME_WAIT是主动关闭终端的状态,也称为2MSL等待状态,是MSL时间的2倍。RFC793[Postel1981c]中指出MSL为2分钟。但是现实中常用的值是30秒、1分钟或者2分钟(linux设置为30秒),linux没有提供可以修改TIME_WAIT状态时间的接口,除非重新设置编译理解系统内核MSLMSL是英文MaximumSegmentLifetime的缩写,译为“最长段寿命”,每个具体的TCP实现都必须选择一个最大段寿命(MaximumSegmentLifetime),而这个最大存活时间就是在丢弃任何段之前的网络。MSL的时间是有限的,因为TCP报文段作为IP数据报在网络中传输,而IP数据报有一个TTL限制了它们的生命周期(timetolive)字段,TTL可以翻译为timetolive,每一个IP数据报经过一个路由器,它的值会减1,当这个值为0时,数据报就会被丢弃,何必等2MSL1。确保有足够的时间让服务器收到ACK,如果没有,就会响应对方新的FIN+ACK包。例如,主动关闭端(client)向被动关闭端(server)发送了最后一个ACK报文段,但是这个ACK报文段可能丢失了。如果服务器没有收到这个ACK,那么服务器在LAST_ACK超时后重新发送FIN+ACK报文段,这样客户端可以在2MSL内收到重新发送的FIN+ACK报文段。如果客户端没有进入TIME_WAIT就发送了最后一个ACK报文而立即释放了连接,那么客户端重新发送的FIN+ACK报文段是收不到的。所以等待2MSL是更安全的断开连接2.TIME_WAIT状态的连接有足够的时间不和后面的连接混在一起。比如发送了一些延迟包,但是如果没有TIME_WAIT,那么它们会被发送到一个新的连接,这样它们就混在一起了,如果是TIME_WAIT,这些延迟包就会被丢弃,等待2MSL。TCP连接的缺点是在2MSL等待期间,这个处于TIME_WAIT状态的连接(客户端的IP地址和端口号,服务端的IP地址和端口号)不能再使用,只能在2MSL结束后才能使用,而这些TIME_WAIT状态占用了很多服务resources,对于web服务,修改内核参数不合理,防止2MSL导致TIME_WAIT过多。对于web服务器,因为我们需要频繁连接mysql、redis或者一些RPC调用,所以会出现大量的主动关闭状态(TIME_WAIT),所以可以修改内核参数限制TIME_WAIT的数量net.ipv4。tcp_max_tw_buckets=20000来限制timewait的数量,防止大量的timewait导致系统负载增加。一旦达到限制值,TIME_WAIT状态的连接将被强制清理并打印系统日志(timewaitbuckettableoverflow),该参数官方文档说明主要用于对抗DDos攻击.net.ipv4.tcp_tw_recycle=1启用timewait快速回收net.ipv4.tcp_timestamps=0时间戳,0禁用,1启用。不能和net.ipv4.tcp_tw_recycle参数同时开启,因为一旦开启net.ipv4.tcp_tw_recycle,服务器会检查数据包的时间戳。服务端不会回复,服务端会把带有“backward”的时间戳包当成“recycle”tw连接的重传数据,而不是新的请求,所以包丢了不会返回,是easyforsynnotrespondtonet.ipv4.tcp_tw_reuse=1enablesreuse,允许TIME-WAITsockets被重新用于新的TCP连接TIME_WAIT总结其实TIME_WAIT是主动断开,所以如果对方主动断开,那么这个TIME_WAIT问题是对方的。所以如果这个问题出现的太多,就从业务入手,比如HTTP服务,NGINX设置keepalive参数(浏览器会复用一个TCP连接来处理多个HTTP请求),然后让客户端断开连接。当然,这个必须要设置。keepalive_timeout的超时时间,因为有些浏览器可能不会主动断开,如果是主动连接mysql、redis等后端调用,可以考虑使用长连接,避免TIME_WAIT过多的问题4.核心longconnection(keepalive)参数调整Linux下默认不开启keepalive,也没有内核参数控制。它需要在TCP套接字中单独启用。Linux内核影响keepalive参数的目的只是为了检测TCP连接是否存活,然后处理异常连接net.ipv4.tcp_keepalive_time=120单位秒,表示多少秒TCP连接开始一个探测报文无数据报文传输时,检测连接是否正常net.ipv4.tcp_keepalive_intvl=5单位秒,前后检测报文的时间间隔=3次检测,超过设置后丢弃5.TCP/UDP内存参数调整(1)TCPsocketbuffernet.ipv4.tcp_mem=94500000915000000927000000TCP内存使用设置指定TCP内存的整体使用量,单位为page。这3个值就是TCP的整体内存[low,pressure,high]。在网络服务中,你可以放大这个值。第一个值tcp_mem[0]:当TCP全局分配的页数低于这个数时,TCP不调整其内存分配第二个值tcp_mem[1]:当TCP分配的内存量超过这个数时pages,进入内存压力模式,TCP调整内存消耗第三个值tcp_mem[2]:TCP全局使用的最大页数,这个值将覆盖任何其他限制,如果超过,所有新的TCP缓冲区(buffer)内存分配会失败其实我们可以把这个值设置的大一点,只要系统不限制内存分配,然后用监控来处理内存问题,一般来说,根据业务选择的配置,就是很难耗尽内存,否则优化的不仅仅是这个参数。单个TCP连接上读写缓冲区(buffer)内存的上限,以字节为单位,这三个值分别是最小值、默认值(会覆盖rmem_default、wmem_default配置)、最大值和最小值:TCPsocket的发送缓冲区(tcp_rmem)/接收缓冲区(tcp_wmem)内存,默认1页(4K)默认值:TCPsocket使用的发送缓冲区(tcp_rmem)/接收缓冲区(tcp_wmem)的初始大小,这个值会覆盖(net.core.wmem_default/net.core.rmem_default),一般设置低于(net.core.wmem_default/net.core.rmem_default)这个值,默认值最大为16K:发送缓冲区(tcp_rmem)/TCPsocket使用的接收缓冲区最大大小(tcp_wmem),这个值不会覆盖(net.core.wmem_max/net.core.rmem_max),默认是4M这两个内核参数的设置是主要是对于每一个TCP连接,使用默认的设置几乎是一样的。如果设置过大,也会出现单个TCP连接占用内存过多的问题。什么是TCP读写缓冲区(buffer)?事实上,一个TCP连接使用的内存量是由读写缓冲区的大小决定的。对于读缓冲区,当收到对端连接的TCP报文时,读缓冲区内存会增加。如果这条消息加上当前读缓冲区如果内存超过tcp_rmem[3]的上限,那么消息就会被丢弃。只有调用read、recv等方法读取TCP流时,readbuffermemory才会减少,所以readbuffermemory是动态变化的,使用多少就分配多少buffer,如果连接空闲,并且用户进程已经消费掉了连接上接收到的所有数据,那么读取缓冲区所用的内存为0。写入缓冲区也是如此。在socket编程中,当调用send或者write的时候,都会导致writebuffer增加,那么什么时候减少呢?也就是当收到对端TCP连接发送的ACK确认消息发送成功后,writebuffer会减少,类似于我给你发文件,我先复制一份给你,我会确认您已收到。只需删除此源文件即可,以免占用空间。如果确认没有收到,那么我会重新发送。因此,读写缓冲区是不断变化的。那么什么样的场景会导致读写缓冲区达到上限呢?就读缓冲区而言,比如在接收TCP点对点报文的时候,对端发送了很多很多的消息。我读完后,不能及时读取(read和recv),导致readbuffer越来越多,最后达到上限。丢弃数据包与写入缓冲区相同。当发送或写入大量数据包时,如果TCP对等体不能及时读取和接收它们,写入缓冲区就会堆积起来。调整系统读写缓冲区参数net.core.rmem_default=4194304默认读取缓冲区大小,单位字节net.core.wmem_default=4194304默认写入缓冲区大小,单位字节net.core.rmem_max=4194304最大读取缓冲区大小,Unitbytenet.core.wmem_max=4194304最大写入缓冲区大小,unitbyte看它的定义,你觉得和net.ipv4.tcp_mem,net.ipv4.tcp_rmem,net.ipv4.tcp_wmem是不是一个意思?其实这些参数(net.ipv4.tcp_mem,net.ipv4.tcp_rmem,net.ipv4.tcp_wmem)只是控制了TCPsocket的内存大小,如果一个TCPsocket申请内存,(net.core.rmem_default,net.core.wmem_default)会被(net.ipv4.tcp_rmem,net.ipv4.tcp_wmem)覆盖,所以(net.core.rmem_default,net.core.wmem_default,net.core.rmem_max,net.core.wmem_max)控制系统所有协议读写缓冲区大小(2)UDP协议内存使用设置net.ipv4.udp_mem=75283210037761505664net.ipv4.udp_rmem_min=4096net.ipv4.udp_wmem_min=4096这些参数是针对UDP协议的,它们与上面TCP的含义一致。其他内核参数net.ipv4.ip_local_port_range=102465000表示出连接的临时端口范围。默认情况下很小:32768到61000,因为活跃的连接需要用到很多临时端口(比如连接mysql,redis),临时端口的最大值为(2^16-1)65535,而ports之前的1000一般都是系统预留的,所以建议设置为1024到65000之间较大的范围。net.core.somaxconn=65535net.core.somaxconn表示socket监听(listen)积压的上限,而backlog是socket的监听队列,是server可以接受的(socket编程中的accpet()函数是建立TCP连接接受连接状态),也就是最大client数处理数据队列,默认值为128,如果在队列满时建立新连接,连接将被拒绝,该值应小于或等于net.ipv4.tcp_max_syn_backlog,因为SYN队列数net.ipv4.tcp_max_syn_backlog参数控制的clients还在连接建立之前,所以设置为65535比较合适。可以打开多少个文件句柄。这是系统级设置。它控制所有进程可以同时打开多少个文件句柄。如果多个进程打开的文件较多,就会出现文件句柄不足的情况。因此,设置一个更大的值。不过需要注意的是,程序打开的文件越多,占用的内存也就越多。所以要根据业务和服务器进行配置。如果要设置一个进程可以打开的文件句柄数,可以使用ulimit-n命令设置,但是这个命令只对当前会话有效。默认值为1024ulimit-n655350,也可以永久写入文件。它限制了每个进程打开文件的数量。vim/etc/security/limits.conf*softnofile655350*hardnofile655350总结现在大部分线上业务,服务器很少暴露在外网,前端一般都有负载均衡,防火墙等代理。甚至服务器也变成了VPC(VirtualIntranet)环境,将这些服务器与外部网络环境隔离开来,从而减少DDOS等一般由外部代理承担的攻击。对于服务器的一些内核性能参数的取值范围,如果网络环境和架构设计的好,可以将一些取值范围的参数设置的过大,将性能设置到极限。这样可以最大程度地发挥服务器的性能,其余使用系统默认参数配置即可。.WEB服务的优化是多方面的。内核参数只是释放服务器应有的性能,更高的承载能力需要从服务器配置、网络、架构、数据库和缓存、实际业务应用等多方面考虑。从不同的调整入手,满足不同的需求RT:上面有些地方可能解释的不对,望大家指正,共同学习
