前言
在当今互联网快速发展的时代,高性能的服务开发已经成为了每个开发人员都需要面对的问题,为了应对日益增长的用户量和请求,高性能服务开发已经成为了一个必要的技能,在这篇博客中,我将介绍如何使用基于Linux内核优化的方法来开发高性能服务。
Linux内核是Linux操作系统的核心部分,它控制着操作系统的各个方面,如内存管理、进程调度、设备驱动等等。由于Linux内核具有高度的可定制性和可扩展性,因此可以通过对其进行优化来提高系统性能和服务性能,我们可以在购买云主机后对服务器环境进行优化,最大化优化linux系统性能,为后续各高性能服务部署打好基础。
源码
Linux服务器内核优化,包括优化系统环境、内核和网络,相关内核优化脚本可参考centos_init.sh
内核参数优化(/etc/sysctl.conf)
accept的网络连接数优化
相关参数:net.core.somaxconn
net.core.somaxconn用于设置监听socket的最大连接数,当应用程序调用listen函数创建一个监听socket时,该参数会限制该socket可以接受的连接数,如C语言中的函数listen(int socketfd,int backlog)用来初始化服务端可连接队列。
该参数的默认值通常是128,增加该参数的值可以提高系统同时接受连接的能力,减小连接被拒绝的可能性。
在实际应用中,该参数通常用于优化高并发网络应用程序的性能,例如,在Web服务器中,当同时有大量连接请求到达时,如果该参数设置过小,可能会导致一些连接被拒绝,从而影响用户体验和系统性能,通过增加net.core.somaxconn的值,可以提高系统的同时接受连接的能力,从而减少连接被拒绝的情况,进而提高系统的吞吐量和响应速度。
注:该参数仅影响监听socket的连接数限制,而不影响已经建立的连接数,如果需要控制已经建立的连接数,可以通过其他手段,如使用连接池等。
方式1
终端执行:
echo "net.core.somaxconn = 2048" >> /etc/sysctl.conf
方式2
echo 2048 > /proc/sys/net/core/somaxconn
但这样系统重启后保存不了
让配置生效
sysctl -p /etc/sysctl.conf
TIME_WAIT 网络连接优化
TIME_WAIT状态是TCP协议中的一种状态,它表示连接已经关闭,但是在一段时间内仍然保持在系统中,以防止可能存在的延迟数据包到达,在大量TCP连接的情况下,TIME_WAIT状态可能会导致系统资源的浪费和性能下降。
参考:TCP 的那些事儿(上)
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
这个命令会输出类似下面的结果:
LAST_ACK 16
SYN_RECV 348
ESTABLISHED 70
FIN_WAIT1 229
FIN_WAIT2 30
CLOSING 33
TIME_WAIT 18098
我们只用关心TIME_WAIT的个数,在这里可以看到,有18000多个TIME_WAIT,这样就占用了18000多个端口。要知道端口的数量只有65535个,占用一个少一个,会严重的影响到后继的新连接。这种情况下,我们就有必要调整下Linux的TCP内核参数,让系统更快的释放TIME_WAIT连接。
echo "net.ipv4.tcp_syncookies = 0" >> /etc/sysctl.conf
echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf
echo "net.ipv4.tcp_tw_recycle = 1" >> /etc/sysctl.conf
echo "net.ipv4.tcp_fin_timeout = 30" >> /etc/sysctl.conf
各参数说明:
net.ipv4.tcp_tw_reuse = 1
该参数的作用是启用TCP连接的地址复用,当该参数设置为1时,TCP连接的本地地址可以被新的连接重用。这意味着当一个连接处于time_wait状态时,它所占用的本地地址可以被新的连接使用,从而减少time_wait状态的数量。
net.ipv4.tcp_tw_recycle = 1
该参数的作用是启用TCP连接的快速回收。当该参数设置为1时,如果一个连接处于time_wait状态,并且它的时间戳比本地系统时间早超过1个小时,那么该连接将被快速回收。
注:这种快速回收的方式可以减少time_wait状态的数量,但是需要注意的是,该参数也可能会导致一些安全问题,因为它假设所有的TCP连接都在同一时间周期内,如果某些连接比较旧,就可能会被错误地回收,导致连接中断或者数据丢失等问题。
net.ipv4.tcp_fin_timeout = 30
修改系統默认的 TIMEOUT 时间,如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60秒。2.2 内核的通常值是180秒,你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB服务器,也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2的危险性比FIN-WAIT-1要小,因为它最多只能吃掉1.5K内存,但是它们的生存期长些。经过这样的优化配置之后,你的服务器的TCP并发处理能力会显著提高。以上配置仅供参考,用于生产环境请根据自己的实际情况
netstat -apn | grep "TIME_WAIT" | wc -l
查看TIME_WAIT状态的连接数量
大流量系统配置提高并发能力
echo "net.ipv4.tcp_keepalive_time = 1200" >> /etc/sysctl.conf
echo "net.ipv4.ip_local_port_range = 10000 65000" >> /etc/sysctl.conf
echo "net.ipv4.tcp_max_syn_backlog = 8192" >> /etc/sysctl.conf
echo "net.ipv4.tcp_max_tw_buckets = 5000" >> /etc/sysctl.conf
net.ipv4.tcp_keepalive_time = 1200
该参数用于设置TCP连接的keepalive时间。它指定了一个TCP连接在没有数据传输的情况下,发送第一个keepalive探测报文的时间间隔,如果在该时间间隔内没有收到对端的响应,系统会继续发送探测报文,直到达到一定的次数或者连接断开为止。
该参数的单位是秒,其默认值为7200秒(即2小时)。如果一个TCP连接的keepalive时间过长,那么可能会导致长时间的空闲连接占用系统资源,从而影响系统性能,如果keepalive时间过短,则可能会频繁地发送探测报文,从而增加网络负载和系统开销。
注:该参数只对处于空闲状态的连接生效,对于正在传输数据的连接无效,因此,它主要用于检测连接是否因为其他原因(如网络故障、对端异常退出等)而被中断。
net.ipv4.ip_local_port_range = 10000 65000
表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为10000到65000
注意:这里不要将最低值设的太低,否则可能会占用掉正常的端口!
net.ipv4.tcp_max_syn_backlog = 65536
记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存的系统则是128。
net.ipv4.tcp_max_tw_buckets = 5000
这个参数是系统同时保持timewait套接字的最大数量。如果超过这个数字,time-wait套接字将立刻被清除并打印警告信息,这个限制仅仅是为了防止简单的DoS攻击。绝对不能过分依靠它或者人为地减小这个值,如果网络实际需要大于缺省值,更应该增加这个值(如果增加了内存之后)。默认为180000,改为5000
注意如此此值过小或者系统网络连接较多时会导致系统(/var/log/messages)报“TCP: time wait bucket table overflow、__ratelimit: 855 callbacks suppressed”错误,此时如果真的是系统负载确实高需要适当调大此数值
查看当前系统配置tcp_max_tw_buckets值
cat /proc/sys/net/ipv4/tcp_max_tw_buckets
查看TIME_WAITE哪个端口占用最大
netstat -n | grep TIME_WAIT | awk -F ' ' '/^tcp/ {print $4}' | sort | uniq -c | sort -brn | head
/proc/sys/net/ipv4/tcp_max_syn_backlog
记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存的系统则是128。如果服务器不堪重负,试试提高这个值。注意!如果你设置这个值大于1024,最好同时调整include/net/tcp.h中的TCP_SYNQ_HSIZE,以保证TCP_SYNQ_HSIZE*16 ≤tcp_max_syn_backlog,然后重新编译内核。
此参数过小并且在系统负载较高的情况下,排除恶意流量攻击,则会报“kernel: possible SYN flooding on port”错误
/proc/sys/net/ipv4/tcp_abort_on_overflow
缺省值是0
当守护进程太忙而不能接受新的连接,就象对方发送reset消息,处理不过来干脆就直接拒绝连接了,默认值是false。这意味着当溢出的原因是因为一个偶然的猝发,那么连接将恢复状态。 只有在你确信守护进程真的不能完成连接请求时才打开该选项,该选项会影响客户的使用。(对待已经满载的sendmail,apache这类服务的时候,这 个可以很快让客户端终止连接,可以给予服务程序处理已有连接的缓冲机会,所以很多防火墙上推荐打开它)
虚拟内存优化
相关参数:swappiness
相关链接:
- http://blog.itpub.net/29371470/viewspace-1250975
- http://bbs.51cto.com/thread-1016268-1.html
- http://blog.csdn.net/woshiwu/article/details/6923463
该参数用于控制系统在物理内存不足时,如何使用交换空间(swap space)。
当系统物理内存不足时,Linux系统会将部分内存数据移动到交换空间中,以腾出物理内存,交换空间一般是硬盘上的一部分空间,速度较慢,因此频繁使用交换空间会导致系统性能下降。
swappiness的值的大小对如何使用swap分区是有着很大的联系,需要根据实际情况进行选择,如果系统有足够的物理内存,并且运行的应用程序较小,则可以设置swappiness=0,最大限度使用物理内存以提高系统性能。
如果系统内存不足或者运行的应用程序较大,则可以将swappiness参数设置较高,以提高系统稳定性。
查看系统里面的swappiness
cat /proc/sys/vm/swappiness
默认输出为60,也就是说系统内存在使用到100-60=40%的时候(即内存使用到了40%时才用swap区),就开始出现有交换分区的使用。大家知道,内存的速度会比磁盘快很多,这样子会加大系统io,同时造的成大量页的换进换出,严重影响系统的性能,所以我们在操作系统层面,要尽可能使用内存,对该参数进行调整
临时调整的方法如下,我们调成20
sysctl vm.swappiness=20
永久调整的话,需要将在/etc/sysctl.conf修改,加上:
vim /etc/sysctl.conf,添加内容vm.swappiness=20
让sysctl各内核参数生效
sysctl -p
查看所有内核参数
sysctl -a
内核参数优化(/etc/security/limits.conf)
打开文件句柄数量优化
文件句柄内核参数设置,默认过小会报“Socket/File: Can’t open so many files”,nginx则会报“Nginx accept() failed (24: Too many open files)” 查看当前系统打开的句柄
lsof | wc -l
优化配置如下:
优化用户最大打开文件数量,缺省是1024,可通过ulimit -n查看
echo "* soft nofile 32768" >> /etc/security/limits.conf
echo "* hard nofile 65536" >> /etc/security/limits.conf
也可以
echo "* - nofile 409600" >> /etc/security/limits.conf
优化用户最大进程数量,可通过ulimit -u查看
echo "* soft nproc 32768" >> /etc/security/limits.conf
echo "* hard nproc 65536" >> /etc/security/limits.conf
也可以
echo "* - nproc 409600" >> /etc/security/limits.conf
- 代表针对所有用户,noproc 是代表最大进程数,nofile 是代表最大文件打开数
也可以针对不同的用户做出不同的限制注意,如下:
echo "@faier soft nproc 32768" >> /etc/security/limits.conf
echo "@root soft nproc 65536" >> /etc/security/limits.conf
这个当中的硬限制是实际的限制,而软限制,是warnning限制,只会做出warning,其实CentOS ulimit命令本身就有分软硬设置,加-H就是硬,加-S就是软默认显示的是软限制
修改完exit退出重新登录就可以见到
注意:如果用* - nproc 409600来配置limits.conf还需要注意参数也受/etc/security/limits.d/90-nproc.conf影响,具体参照 http://blog.csdn.net/kumu_linux/article/details/8301760、http://blog.csdn.net/cnbird2008/article/details/8666620 需要将/etc/security/limits.d/90-nproc.conf改成内容如下
* soft nproc unlimitedroot soft nproc unlimited
显示当前的各种用户进程限制
ulimit -a
查看当前打开进程总数
pstree -p `ps -e | grep root | awk '{print $1}'` | wc -l