Linux 性能优化
一、优化Linux文件打开最大数
在Linux下有时会遇到Socket/File : Can't open so many files的问题。其实Linux是有文件句柄限制的,而且Linux默认一般都是1024(阿里云主机默认是65535)。在生产环境中很容易到达这个值,因此这里就会成为系统的瓶颈。
1、查看方法:
使用ulimit -a 或者 ulimit -n
open files (-n) 1024 是linux操作系统对一个进程打开的文件句柄数量的限制(也包含打开的套接字数量)
这里只是对用户级别的限制,其实还有个是对系统的总限制,查看系统总线制:
# cat /proc/sys/fs/file-max
即file-max是设置系统所有进程一共可以打开的文件数量 。同时一些程序可以通过setrlimit调用,设置每个进程的限制。如果得到大量使用完文件句柄的错误信息,是应该增加这个值。这项参数是系统级别的。
2、修改方法:
临时生效:
# ulimit -SHn 10000
其实ulimit 命令身是分软限制和硬限制,加-H就是硬限制,加-S就是软限制。默认显示的是软限制,如果运行ulimit 命令修改时没有加上-H或-S,就是两个参数一起改变。
软限制和硬限制的区别:硬限制就是实际的限制,而软限制是警告限制,它只会给出警告。
永久生效:
要想ulimits 的数值永久生效,必须修改配置文件/etc/security/limits.conf
在该配置文件中添加
* soft nofile 65535
* hard nofile 65535
echo "* soft nofile 65535" >> /etc/security/limits.conf
echo "* hard nofile 65535" >> /etc/security/limits.conf
* 表示所用的用户
修改系统总限制
其实上的修改都是对一个进程打开的文件句柄数量的限制,我们还需要设置系统的总限制才可以。
假如,我们设置进程打开的文件句柄数是1024 ,但是系统总线制才500,所以所有进程最多能打开文件句柄数量500。从这里我们可以看出只设置进程的打开文件句柄的数量是不行的。所以需要修改系统的总限制才可以。
echo 6553560 > /proc/sys/fs/file-max
上面是临时生效方法,重启机器后会失效;
永久生效方法:
修改 /etc/sysctl.conf, 加入
fs.file-max = 6553560 重启生效
二、内核参数优化
Sysctl命令及linux内核参数调整
1、Sysctl命令用来配置与显示在/proc/sys目录中的内核参数.如果想使参数长期保存,可以通过编辑/etc/sysctl.conf文件来实现。
命令格式:
sysctl [-n] [-e] -w variable=value
sysctl [-n] [-e] -p (default /etc/sysctl.conf)
sysctl [-n] [-e] –a
常用参数的意义:
-w 临时改变某个指定参数的值,如
# sysctl -w net.ipv4.ip_forward=1
-a 显示所有的系统参数
-p从指定的文件加载系统参数,默认从/etc/sysctl.conf 文件中加载,如:
# echo 1 > /proc/sys/net/ipv4/ip_forward
# sysctl -w net.ipv4.ip_forward=1
以上两种方法都可能立即开启路由功能,但如果系统重启,或执行了
# service network restart
命令,所设置的值即会丢失,如果想永久保留配置,可以修改/etc/sysctl.conf文件,将 net.ipv4.ip_forward=0改为net.ipv4.ip_forward=1
2、linux内核参数调整:linux 内核参数调整有两种方式
方法一:修改/proc下内核参数文件内容,不能使用编辑器来修改内核参数文件,理由是由于内核随时可能更改这些文件中的任意一个,另外,这些内核参数文件都是虚拟文件,实际中不存在,因此不能使用编辑器进行编辑,而是使用echo命令,然后从命令行将输出重定向至 /proc 下所选定的文件中。如:将 timeout_timewait 参数设置为30秒:
# echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
参数修改后立即生效,但是重启系统后,该参数又恢复成默认值。因此,想永久更改内核参数,需要修改/etc/sysctl.conf文件
方法二.修改/etc/sysctl.conf文件。检查sysctl.conf文件,如果已经包含需要修改的参数,则修改该参数的值,如果没有需要修改的参数,在sysctl.conf文件中添加参数。如:
net.ipv4.tcp_fin_timeout=30
保存退出后,可以重启机器使参数生效,如果想使参数马上生效,也可以执行如下命令:# sysctl -p
3、sysctl.conf 文件中参数设置及说明
proc/sys/net/core/wmem_max 最大socket写buffer,可参考的优化值:873200
/proc/sys/net/core/rmem_max 最大socket读buffer,可参考的优化值:873200
/proc/sys/net/ipv4/tcp_wmem TCP写buffer,可参考的优化值: 8192 436600 873200
/proc/sys/net/ipv4/tcp_rmem TCP读buffer,可参考的优化值: 32768 436600 873200
/proc/sys/net/ipv4/tcp_mem
同样有3个值,意思是:
net.ipv4.tcp_mem[0]:低于此值,TCP没有内存压力.
net.ipv4.tcp_mem[1]:在此值下,进入内存压力阶段.
net.ipv4.tcp_mem[2]:高于此值,TCP拒绝分配socket.
上述内存单位是页,而不是字节.可参考的优化值是:786432 1048576 1572864
proc/sys/net/core/netdev_max_backlog 进入包的最大设备队列.默认是300,对重负载服务器而言,该值太低,可调整到1000
/proc/sys/net/core/somaxconn listen()的默认参数,挂起请求的最大数量.默认是128.对繁忙的服务器,增加该值有助于网络性能.可调整到256.
proc/sys/net/core/optmem_max socket buffer的最大初始化值,默认10K
/proc/sys/net/ipv4/tcp_max_syn_backlog 进入SYN包的最大请求队列.默认1024.对重负载服务器,可调整到2048
/proc/sys/net/ipv4/tcp_retries1 放弃回应一个TCP连接请求前,需要进行多少次重试
/proc/sys/net/ipv4/tcp_retries2 TCP失败重传次数,默认值15,意味着重传15次才彻底放弃.可减少到5,尽早释放内核资源.
/proc/sys/net/ipv4/tcp_keepalive_time 默认7200s
/proc/sys/net/ipv4/tcp_keepalive_intvl 默认75s
/proc/sys/net/ipv4/tcp_keepalive_probes 默认9
意思是如果某个TCP连接在idle 2个小时后,内核才发起probe.如果probe 9次(每次75秒)不成功,内核才彻底放弃,认为该连接已失效.对服务器而言,显然上述值太大. 可调整到: tcp_keepalive_time 1800 tcp_keepalive_intvl 30 tcp_keepalive_probes 3
/proc/sys/net/ipv4/ip_local_port_range 指定端口范围的一个配置,默认是32768 61000,已够大.
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_orphan_retries=0 关闭TCP连接之前重试多少次
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout = 30 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
net.ipv4.tcp_keepalive_time = 1200 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.ip_local_port_range = 1024 65000 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
net.ipv4.ip_conntrack_max=655360 在内核内存中netfilter可以同时处理的“任务”(连接跟踪条目)
net.ipv4.icmp_ignore_bogus_error_responses=1 开户恶意icmp错误消息保护
net.ipv4.tcp_max_syn_backlog = 8192 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets = 5000 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默认为 180000,改为 5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。
BAT企业生产环境/etc/sysct.conf内核参数:
net.ipv4.ip_forward = 0 #禁用包过滤功能
net.ipv4.conf.default.accept_source_route = 0 #禁用所有IP源路由
net.ipv4.tcp_syncookies = 1 #开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies来处理
net.ipv4.tcp_tw_reuse = 1 #开启TCP连接复用功能,允许将time_wait sockets重新用于新的TCP连接(主要针对time_wait连接)
net.ipv4.tcp_tw_recycle = 1 #开启TCP连接中time_wait sockets的快速回收
net.ipv4.tcp_timestamps = 1 #时间戳可以避免序列号的卷绕。一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉
net.ipv4.tcp_timestamps=1 #选择性应答(SACK)是TCP的一项可选择性,可以提高某些网络中所有可用带宽的使用效率
net.ipv4.tcp_fack=1 #打开FACK(forward ACK)拥塞避免和快速重传功能
net.ipv4.tcp_retrans_collapse=1 #打开重传重组包功能,为0的时候关闭重传重组包功能
net.ipv4.tcp_fin_timeout = 10 #如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60 秒。2.2 内核的通常值是180秒,你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB服务器,也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2的危险性比FIN-WAIT-1要小,因为它最多只能吃掉1.5K内存,但是它们的生存期长些
net.ipv4.tcp_keepalive_time = 120 #表示当keepalive起用的时候,TCP发送keepalive消息的频度(单位:秒)
#
net.ipv4.tcp_keepalive_probes = 9
#
net.ipv4.tcp_keepalive_intvl = 45
#
kernel.sysrq = 0
kernel.core_uses_pid = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
vm.swappiness = 10
net.ipv4.neigh.default.gc_stale_time = 120
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
net.ipv4.tcp_max_tw_buckets = 50000
net.ipv4.tcp_max_syn_backlog = 65536
net.core.netdev_max_backlog = 32768
net.core.somaxconn = 32768
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.ipv4.tcp_max_orphans = 3276800 #系统所能处理不属于任何进程的TCP sockets最大数量
net.ipv4.ip_local_port_range = 5000 65535 #程序可用端口范围
net.ipv4.tcp_synack_retries = 2 #显示或设定Linux在回应SYN要求时尝试多少次重新发送初始SYN,ACK封包后才决定放弃
net.ipv4.tcp_syn_retries = 2 #对于一个新建连接,内核要发送多少个SYN连接请求才决定放弃
net.ipv4.conf.lo.arp_announce = 2
fs.file-max = 200001 #表示文件句柄的最大数量
三、Linux内核报错剖析
Linux内核日志一般存在messages日志中,可以通过命令tail -fn 100 /var/log/messages查看,觉见内核报错日志及生产环境解决方案:
1、Linux内核抛出net.ipv4.tcp_max_tw_buckets错误,代码如下:
Sep 23 04:45:55 localhost kernel:TCP:time wait bucket table overflow
根据TCP协议的三次握手及四次挥手断开连接规定,发起socket主动关闭的一方socket将进入TIME_WAIT状态,TIME_WAIT状态将持续2个WSL,如果该值过小,当系统TIME_WAIT数量起过默认设置的值时,即会抛出上述的警告信息,这是需要增加net.ipv4.tcp_max_tw_buckets的值,警告信息才会消失,也不能设置过大,对于一个处理大量短连接的服务器,如果是由服务器关闭客户端的连接,将导致服务端存在大量的处于TIME_WAIT状态的socket,甚至比处理established状态下的soket多得多,严重影响服务器的处理能力,甚至耗尽可用的socket而停止服务,TIME_WAIT是TCP协议用以保证被重新分配的socket不会受到之前残留的延迟重发报文影响的机制,是TCP传输必要的逻辑保证。
2、Linux内核抛出Too many open files错误,代码如下:
socket:Too many open files (24)
Linux内核对应每个用户打开的文件最大数下般为1024,需要将该值调高满足大并发网站的访问。
每个用户打开文件最大数和进程数永久设置方法:将以下代码加入内核限制文件: /etc/security/limits.conf的末尾,退出终端,重新登录即生效。
* soft noproc 65535
* hard noproc 65535
* soft nofile 65535
* hard nofile 65535
3、Linux内核抛出possible SYN flooding on port 80.Sending cookies错误,代码如下:
May 31 14:20:14 localhost kernel:possible SYN flooding on port 80. Sending cookies.
此问题是由于SYN队列已满,而触发SYN cookies,一般是由于大量的访问或者恶意访问导致,也称之为SYN flooding洪水攻击。
完整的三次握手,假设一个用户A向服务器发送了SYN报文后突然死机或者掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成),这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接,这段时间的长度为SYN timeout,一般来说这个时间是分钟的数量级(30s~2min)。
如果被恶意的攻击者模拟这种情况,服务器将为了维护一个非常大的半连接列表而消耗非常多的资源,数以万计的半连接,此时从正常客户的角度来看,服务器失去响应,服务器拒绝提供服务,服务器受到了DDOS攻击,这里攻击的手段为DDOS中SYN flooding 攻击(SYN 洪水攻击)。
防护DDOS攻击有两种手段:一是基于硬件专业防火墙;二是基于Linux内核简单防护。如果攻击流量特别大,单纯配置内核参数是无法抵挡的,还得依靠专业级硬件防火墙,以下为Linux内核防护DDOS优化参数,添加如下代码即可:
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_keepalive_time=1200
net.ipv4.tcp-syncookies=1
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.ip_local_port_range=1024 65000
net.ipv4.tcp_max_syn_backlog=8192
net.ipv4.tcp_max_tw_buckets=8000
net.ipv4.tcp_synack_retries=2
net.ipv4.tcp_syn_retries=2
4、Linux内核抛出nf_conntrack:table full,dropping packet.错误,代码如下:
May 6 11:15:07 localhost kernel: nf_conntrack:table full, dropping packet.
由于该服务器开记了iptables防火墙,Web服务器收到了大量的连接。iptables会把所有的连接都做连接跟踪处理,这样iptables就会有一个连接跟踪表,当这个表满的时候,就会出现上面的错误。ip_conntrack是Linux NAT的一个跟踪连接条目的模块,ip_conntrack横块会使用一个哈希表记录TCP通信协议的established connection记录。
如果是CentOS 6.X系统,需执行modprobe nf_conntrack命令,然后在内核优化文件中加入如下代码,sysctl -p使其内核文件生效,即可解决报错。
net.nf_conntrack_max=655360
net.netfilter.nf_conntrack_tcp_timeout_established=36000
如果是CentOS 5.X系统,需执行modprobe nf_conntrack命令,然后在内核优化文件中加入如下代码,sysctl -p使其内核文件生效,即可解决报错。
net.ipv4.ip_conntrack_max=655350
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established=10800
五、影响服务器性能因素
影响企业生产环境Linux服务器性能的因素有很多。一般分为两大类,即操作系统层级和应用程序级别:
1、操作系统级别:
内存 CPU 磁盘I/O 网络I/O带宽
* 大量的 page-in IO 请求可能导致内存队列被塞满
* 网卡的巨量吞吐可能导致 CPU 资源耗尽
* 系统尝试保持释放内存队列时可能耗尽 CPU 资源
* 来自内存的大量磁盘写入请求可能导致 CPU 资源和 IO 通道耗尽
2、应用程序及软件:
Nginx MySQL Tomcat PHP
* IO 限制型——一个 IO 限制型的应用需要大量的内存和基础存储设备占用。 因其需要大量的数据读写请求,此类应用对 CPU 和网络需求不高(除非存储系统在网络上) 。 IO 限制型应用使用 CPU 资源来进行 IO 操作且常进入睡眠状态。 数据库应用常被认为属于此类。
* CPU 限制型——一个 CPU 限制型应用需要大量的 CPU 资源,来进行批量的处理或大量的计算。大容量 web 服务,mail 服务,以及任何类型的渲染服务都被归到此类。
3、Linux系统性能评估标准:
影响性能因素 好 坏 糟糕
CPU user% + sys%< 70% user% + sys%= 85% user% + sys% >=90%
内存 Swap In(si)=0Swap Out(so)=0 Per CPU with 10 page/s More Swap In & Swap Out
磁盘 iowait % < 20% iowait % =35% iowait % >= 50%
其中:
%user:表示CPU处在用户模式下的时间百分比。
%sys:表示CPU处在系统模式下的时间百分比。
%iowait:表示CPU等待输入输出完成时间的百分比。
swap in:即si,表示虚拟内存的页导入,即从SWAP DISK交换到RAM
swap out:即so,表示虚拟内存的页导出,即从RAM交换到SWAP DISK。
4、Linux系统性能分析工具
常用系统性能分析命令为 vmstat、sar、iostat、netstat、free、ps、top、iftop等。
常用系统性能组合分析命令如下:
vmstat、sar、iostat 检测是否是CPU瓶颈。
free、vmstat 检测是否是内存瓶颈。
iostat 检测是否是硬盘I/O瓶颈。
netstat、iftop 检测是否是网络带宽瓶颈。
六、Linux服务器性能评估与优化
1、Linux系统整体性能评估
uptime命令主要用一查看当前服务器整体性能,例如CPU、负载、内存等值的总览:
#uptime
11:51:00 up 2:11, 1 user, load average: 0.00, 0.01, 0.05
load average 负载有3个值,分别表示最近1min、5min、15min系统的负载,3个值的大小一般不能大于系统逻辑CPU核数的2倍。
2、CPU性能评估
##利用vmstat命令监控系统CPU,该命令可以显示关于系统各种资源之间相关性能的简要信息,主要用它来查看CPU负载及队列情况。
#vmstat 2 10 每隔两秒显示一次统计信息显示10次
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 3647880 2108 168648 0 0 4 0 53 41 0 0 100 0 0
0 0 0 3647840 2108 168648 0 0 0 1 240 161 0 0 100 0 0
vmstat输出结果详解如下:
r 该列表示运行和等待CPU时间片的进程数,这个值如果长期大于系统CPU的个数,说明CPU不足,需要增加CPU。
b 该列表示在等待资源的进程数,比如正在等待I/O或者内存交换等。
us 显示了用户进程消耗的CPU时间百分比,us的值比较高时,说明用户进程消耗的CPU时间多,如果长期大于50%,就需要考虑优化程序或算法。
sy 显示了内核进程消耗的CPU时间百比,sy的值较高时,说明内核消耗的CPU资源很多。
us+sy 参考值 80%,如果 us+sy大于80%说明可能存在CPU资源不足。
##利用sar命令监控系统CPU,sar功能很强大,可以对系统的每个方面进行单独的统计,但是使用sar命令会增加系统开销,不过这些开销是可以评估的,对系统的统计结果不会有很大影响。
#sar -u 2 10 显示CPU的统计信息,每两秒显示一次显示两次
Linux 3.10.0-862.14.4.el7.x86_64 (tang) 11/14/2018 _x86_64_ (1 CPU)
12:16:00 PM CPU %user %nice %system %iowait %steal %idle
12:16:02 PM all 0.50 0.00 0.50 0.00 0.00 99.00
12:16:04 PM all 0.00 0.00 0.00 0.00 0.00 100.00
%user 显示了用户进程消耗的CPU时间百分比
%nice 显示了运行正常的进程所消耗的CPU时间百分比
%system 显示了系统进程所占用的CPU时间百分比
%iowait 显示了I/O等待所占用的CPU时间百分比
%steal 显示了在内存相对紧张的环境下pagein强制对不同的页面进行的steal操作
%idle 显示了CPU处在空闲状态的时间百分比
3、内存性能评估
利用free指令监控内存,free是监控Linux内存使用状况最常用的指令。
#free -h
total used free shared buff/cache available
Mem: 3.9G 214M 3.5G 11M 166M 3.4G
Swap: 2.0G 0B 2.0G
##应用程序可用内存/系统物理内存大于70%时,表示系统内存资源非常充足,不影响系统性能;
##应用程序可用内存/系统物理内存小于20%时,表示系统内存资源紧缺,需要增加系统内存;
##20%<应用程序可用内存/系统物理内存小于70%时,表示系统内存资源基本能满足应用需求,暂时不影响系统性能。
4、磁盘I/O性能评估
利用iostat评估磁盘性能,监控磁盘I/O读写及带宽。
#iostat -d 2 10
Linux 3.10.0-862.14.4.el7.x86_64 (tang.tang.com) 11/14/2018 _x86_64_ (4 CPU)
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
scd0 0.00 0.10 0.00 1028 0
sda 0.95 31.02 4.54 307596 45032
dm-0 0.75 29.97 4.33 297158 42967
dm-1 0.01 0.22 0.00 2228 0
##kB_read/s 表示每秒读取的数据块数;
##kB_wrtn/s 表示每秒写入的数据块数;
##kB_read 表示每秒读取的所有块数;
##kB_wrtn 表示每秒写入的所有块数;
#sar -d 2 10
Linux 3.10.0-862.14.4.el7.x86_64 (tang.tang.com) 11/14/2018 _x86_64_ (4 CPU)
12:29:33 PM DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util
12:29:35 PM dev11-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
12:29:35 PM dev8-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
12:29:35 PM dev253-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
12:29:35 PM dev253-1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
##await 表示平均每次设备I/O操作的等待时间(以ms为单位)
##svctm 表示平均每次设备I/O操作的服务时间(以ms为单位)
##%util 表示ls中有百分之几的时间用于I/O操作
5、网络性能评估
##通过ping命令检测网络接口状况;
##通过netstat -i 组合检测网络接口状况;
##通过netstat -r 组合检测系统的路由表信息;
##通过sar -n 组合显示系统的网络运行状态。
通过iftop -i eth0 可以查看网卡流量:
##<= 客户端流入的流量
##=> 服务器端流出的流量
##TX 发送流量
##RX 接收流量
##TOTAL 总流量
##cumm 运行iftop到目前时间的总流量
##peak 流量峰值
##rates 分别表示过去2s、10s、40sr的平均流量