Linux 性能优化

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的平均流量