Linux操作系统是现在服务器首选的操作系统。在linux默认的系统参数下,linux对高并发的支持不是很好。小编从事Linux下应用开发多年。关于linux系统下的高并发,我踩过的坑,踩过的坑怎么解决,下面罗列一下,供大家参考,避免再次掉坑。Linux应用程序运行时出现Toomanyopenfiles问题的分析及解决方案出现此提示的原因是程序打开的文件socket连接数超过了系统设置值。查看每个用户允许打开的最大文件数ulimit-a其中openfiles(-n)1024表示每个用户允许打开的最大文件数为1024当前系统文件句柄的最大数量仅用于查看,不能设置和修改cat/proc/sys/fs/file-max查看进程的打开文件限制cat/proc/10446(pid)/limitssetopenfilesnumericalmethodulimit-n65535这种设置方法重启后会恢复默认值。永久设置方法:在vim/etc/security/limits.conf最后添加*softnofile65535*hardnofile65535生效,需要重启系统。经此修改后,问题得到有效解决。Linux高并发下time_wait过多问题分析及解决现象是在高并发场景下,服务器运行应用卡顿。排错方法:查看服务器配置:netstat-ant|awk'/^tcp/{++S[$NF]}END{for(ainS)print(a,S[a])}'发现数是在time_wait太多了,有几万条,应该是大量socket处于TIME_WAIT状态。如果客户端的并发量持续偏高,此时会出现部分客户端连接不上的情况。TCP连接状态描述:CLOSED:没有连接处于活动状态或正在进行中LISTEN:服务器正在等待传入调用SYN_RECV:连接请求已到达,等待确认SYN_SENT:应用程序已启动,打开连接说完成FIN_WAIT2:The对方已同意释放ITMED_WAIT:Waitingforallpacketstodie主动方没有TIME_WAIT等待。关闭之前的连接后,主动方和被动方建立新的TCP连接。此时被动方重传或延迟FIN包,将直接影响新的TCP连接;同样网络情况不好没有TIME_WAIT等待,关闭连接后也没有新的连接。当被动方重传或延迟FIN包时,会返回一个RST包给被动方,这可能会影响被动方的其他业务连接。如何解决TIME_WAIT过多的问题,答案如下:编辑内核文件/etc/sysctl.conf,添加如下内容:net.ipv4.tcp_syncookies=1#表示启用SYNCookies。当SYN等待队列溢出时,启用cookies进行处理,可以防止少量的SYN攻击。默认为0,表示关闭;net.ipv4.tcp_tw_reuse=1#表示启用重用。允许TIME-WAIT套接字被重新用于新的TCP连接,默认为0,表示关闭;net.ipv4.tcp_tw_recycle=1#表示开启TCP连接中TIME-WAITsockets的快速回收,默认为0,表示关闭。net.ipv4.tcp_fin_timeout=30#修改默认的TIMEOUT时间,然后执行/sbin/sysctl-p使参数生效。简单的说就是让系统的TIMEWAIT重用,快速恢复。更多针对Linux的性能优化如果你的系统连接数比较多,如果经过以上配置调优后性能不理想,可以优化TCP的可用端口范围,进一步提高服务器的并发能力。还是在/etc/sysctl.conf文件中,添加如下配置:vi/etc/sysctl.conf#表示启用keepalive时TCP发送keepalive报文的频率。默认为2小时,将其更改为20分钟。net.ipv4.tcp_keepalive_time=1200#代表传出连接的端口范围。Smallbydefault:32768to61000,改为1024to65000net.ipv4.ip_local_port_range=102465000#表示SYN队列的长度,默认是1024,增加队列长度到8192可以容纳更多等待的网络连接连接的。net.ipv4.tcp_max_syn_backlog=8192#表示系统同时维持TIME_WAIT套接字的最大数量。如果超过这个数字,TIME_WAIT套接字将被立即清除并打印一条警告消息。默认是180000,改成5000。对于Apache、Nginx等服务器,上面几行的参数可以很好的减少TIME_WAITsockets的数量,但是对于squid,效果不是很好。这个参数可以控制TIME_WAITsockets的最大数量,防止squid服务器被大量的TIME_WAITsockets拖死。net.ipv4.tcp_max_tw_buckets=5000Linux内核更多参数优化说明vim/etc/sysctl.conf1,net.ipv4.tcp_max_syn_backlog=65536记录未收到客户端确认信息的连接请求的最大值。对于内存大于128M的系统,默认值为1024,对于内存小于128M的系统,默认值为128。SYNFlood攻击利用TCP协议的握手缺陷,伪造虚假的源IP地址,发送大量TCP-SYN半开连接到目标系统,最终导致目标系统的Socket队列资源耗尽,无法接受新的连接。为了应对这种攻击,现代Unix系统中普遍采用多连接队列处理来缓冲(而不是解决)这种攻击。它使用一个基本队列来处理正常的全连接应用程序(Connect()和Accept()),它是使用另一个队列单独存储半开连接。当这种双队列处理方式与其他系统内核措施(如Syn-Cookies/Caches)相结合时,可以有效缓解小规模的SYNFlood攻击(事实证明<1000p/s)增加SYN长度队列可以容纳更多等待连接的网络连接。一般遭受SYNFlood攻击的网站都会有大量的SYN_RECV状态。因此,增大tcp_max_syn_backlog的值可以增加抵抗syn攻击的能力。2.net.core.netdev_max_backlog=32768当每个网络接口接收数据包的速率快于内核处理这些数据包的速率时,允许发送到队列的最大数据包数。3.net.core.somaxconn=32768调整系统同时发起的并发TCP连接数。可能需要增加连接保留值以应对大量突然传入的连接请求。如果同时收到大量连接请求,使用较大的值会增加支持的挂起连接数,从而减少连接失败的次数。大型监听队列也有助于防止DDoS攻击。默认情况下,挂起请求的最大数量为128。查看实时内核实时丢包命令:netstat-sulocation:/proc/sys/4,net.core.wmem_default=8388608该参数指定sendsocketbuffersize的默认值(以字节为单位)5、net.core.rmem_default=8388608该参数指定接收套接字缓冲区大小的默认值(以字节为单位)6、net.core.rmem_max=16777216该参数指定接收套接字缓冲区大小的最大值(以字节为单位)7.net.core.wmem_max=16777216该参数指定发送套接字缓冲区大小的最大值(以字节为单位)8.net.ipv4.tcp_timestamps=0时间戳可以防止那些伪造的序列号。1G宽带线路可能会重新遇到具有异常值的旧序列号(如果它是上次生成的)。时间戳使内核能够接受这种“异常”数据包。这里需要关闭它以提高性能。9.net.ipv4.tcp_synack_retries=2对于远程连接请求SYN,内核会发送一个SYN+ACK数据报来确认收到最后一个SYN连接请求包。这是所谓的三向握手机制的第二步。这决定了内核在放弃连接之前发送的SYN+ACK的数量。不应大于255,默认值为5,对应180秒左右。(这个值可以根据tcp_syn_retries来确定)10.net.ipv4.tcp_syn_retries=2对于一个新的连接,内核应该发送多少次SYN连接请求才决定放弃。不应大于255,默认值为5,对应180秒左右。(对于负载较重、物理通信较好的网络,该值偏高,可修改为2。该值仅针对外部连接,传入连接由tcp_retries1决定)\#net.ipv4.tcp_tw_len=111,net.ipv4.tcp_tw_reuse=1表示启用重用,允许TIME-WAITSockets被重用于新的TCP连接,默认为0,表示关闭。这对于快速重启一些服务和启动后提示端口已被使用非常有帮助。12.net.ipv4.tcp_mem=94500000915000000927000000tcp_mem有3个INTEGER变量:low、pressure、highlow:当TCP使用的内存页数低于这个值时,TCP没有内存压力,TCP不会考虑释放内存。(理想情况下,这个值应该与分配给tcp_wmem的第二个值匹配。这个第二个值表示最大页面大小乘以最大并发请求数除以页面大小(131072*300/4096)压力:当TCP使用更多时memorypagesthanthisvalue,TCPtrytostabilizeitsmemoryusage,enterthepressuremode,andexitsthepressurestatewhenthememoryconsumptionlowerthanthisvalue.(理想情况下,此值应为TCP可以使用的总缓冲区最大区域size(204800*300/4096)high:允许所有TCPSockets排队缓冲数据报的页数,超过这个值会拒绝TCP连接,所以不要太保守(512000*300/4096).在这种情况下,提供的值很大,它可以处理很多连接,是预期的2.5倍;或者使现有连接能够传输2.5倍的数据。一般这些值是根据数量计算的系统启动时的系统内存。13.net.ipv4.tcp_max_orphans=3276800系统可以处理不属于任何进程的TCP套接字的最大数量。如果超过这个数量,不属于任何进程的连接将被立即重置,同时显示警告信息。之所以设置这个限制纯粹是为了防御那些简单的DoS攻击,不要依赖这个或者人为降低这个限制14、net.ipv4.tcp_fin_timeout=30如果socket被本地请求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对等方可能会出错而永远不会关闭连接,甚至会意外崩溃。默认值为60秒。2.2kernel的通常值是180秒,可以按这个设置,但是要记住,即使你的机器是轻载的WEB服务器,也有大量deadsockets导致内存溢出的风险,FIN-WAIT-2没有FIN-WAIT-1危险,因为它最多只能吃掉1.5K的内存,但它们的生命周期更长。15.net.ipv4.ip_conntrack_max=10000设置系统限制跟踪的最大TCP连接数(CentOS5.6没有这个参数)同时还涉及一个TCP拥塞算法问题,可以使用如下命令查看拥塞情况由机器算法控制模块:sysctlnet.ipv4.tcp_available_congestion_control几种算法的分析详见以下:TCP拥塞控制算法优缺点、适用环境、性能分析。例如,您可以尝试高延迟的hybla和中等延迟的htcp算法。如果要设置TCP拥塞算法为hybla#设置TCP拥塞算法net.ipv4.tcp_congestion_control=hybla对于高于3.7.1的内核版本,我们可以启用tcp_fastopen:#Enabletcp_fastopennet.ipv4.tcp_fastopen=3iptables相关如非必要,关闭或卸载iptables防火墙,并阻止内核加载iptables模块。这些模块影响并发性能。IO事件分发机制要在Linux中实现高并发的TCP连接,需要确认应用程序是否使用了合适的网络I/O技术和I/O事件分发机制。可用的I/O技术有同步I/O、非阻塞同步I/O和异步I/O。在高TCP并发的情况下,如果使用同步I/O,这会严重阻塞程序的运行,除非为每个TCP连接的I/O创建一个线程。但是过多的线程会由于系统对线程的调度而造成巨大的开销。因此,在TCP并发较高的情况下,不建议使用同步I/O。这时候可以考虑非阻塞同步I/O或者异步I/O。非阻塞同步I/O技术包括使用select()、poll()、epoll等机制。异步I/O的技术就是使用AIO。从I/O事件派发机制来看,使用select()是不合适的,因为它支持的并发连接数是有限的(一般在1024以内)。如果考虑性能,poll()也不合适。虽然它可以支持很高的TCP并发数,但是由于它的“轮询”机制,当并发数很高的时候,它的运行效率是相当低的,并且可能会出现I/O事件分布不均导致“饥饿”"一些TCP连接上的I/O。而如果使用epoll或者AIO,就没有上述问题(早期Linux内核的AIO技术实现是通过在内核中为每个I/O请求创建一个线程来实现的,这种实现机制是在高负载的情况下并发TCP连接使用AIO也存在严重的性能问题。但在最新的Linux内核中,AIO的实现得到了改进)。小结综上所述,在开发支持高并发TCP连接的Linux应用时,尽量使用epoll或者AIO技术来实现对并发TCP连接的I/O控制,这样会提高程序在高并发TCP上的性能连接。支持提供高效的I/O保证。经过上述优化配置后,服务器的TCP并发处理能力将得到显着提升。以上配置仅供参考。生产环境,请根据自己开发系统的实际部署,调整、观察、调整。参考文章:高并发Linux系统与内核参数优化OptimizingLinuxKernelParameters
