为什么要性能调优?

大部分的linux发行版是为了完全兼容市场中大部分计算机而设计的。这是一个相当混杂的硬件集合(硬盘,显卡,网卡,等等)。所以Red Hat, Suse,Mandriva和其他的一些发行版厂商选择了一些保守的设置来确保安装成功。
简单地说:你的发行版运行的很好,但是它可以运行地更好!
比如,可能有一个具体一些特殊特性的高级硬盘,而这些特性在标准配置的情况下可能就没被启用。

磁盘子系统的调优

对于Linux的Ext3/4来说,几乎在所有情况下都有所帮助的一个参数是关闭文件系统访问时间,在/etc/fstab下看看你的文件系统 有没有noatime参数.atime 是最近访问文件的时间,每当访问文件时,底层文件系统必须记录这个时间戳。因为系统管理员很少使用 atime,禁用它可以减少磁盘访问时间。禁用这个特性的方法是,在 /etc/fstab 的第四列中添加 noatime 选项。

网络调优

tcp连接保持管理:

如果在该参数指定时间内某条连接处于空闲状态,则内核向远程主机发起探测
[bash]net.ipv4.tcp_keepalive_time = 7200[/bash]

内核向远程主机发送的保活探测的时间间隔
[bash]net.ipv4.tcp_keepalive_intvl = 75[/bash]

内核发送保活探测的最大次数,如果探测次数大于这个数,则断定远程主机不可达,则关闭该连接并释放本地资源
一个连接7200s空闲后,内核会每隔75秒去重试,若连续9次则放弃。这样就导致一个连接经过2h11min的时间才能被丢弃,降低该值能够尽量减小失效连接所占用的资源,而被新的连接所使用。
[bash]net.ipv4.tcp_keepalive_probes = 9[/bash]

tcp连接管理:

表示在每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
[bash]net.core.netdev_max_backlog=3000[/bash]

控制每个端口的tcp syn的队列长度,来自客户端的连接请求需要排队,直至服务器接受,如果连接请求数大于该值,则连接请求会被丢弃,客户端无法连接服务器,一般服务器要提高此值
[bash]net.ipv4.tcp_max_syn_backlog = 1024[/bash]

控制内核向某个socket的ack,syn段(三次握手的第二次握手)重新发送响应的次数,降低此值可以尽早检测到来自远程主机的连接失败尝试
[bash]net.ipv4.tcp_synack_retries = 5[/bash]

控制内核向已建立连接的远程主机重新发送数据的次数,降低此值,可以尽早的检测连接失效
[bash]net.ipv4.tcp_retries2 = 15[/bash]

SYN Cookie是对TCP服务器端的三次握手协议作一些修改,专门用来防范SYN Flood攻击的一种手段。它的原理是,在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时,不分配一个专门的数据区,而是根据这个SYN包计算出一个cookie值。在收到TCP ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接。
[bash]net.ipv4.tcp_syncookies = 1[/bash]

如下的sysctl命令用于改变安全设置,但是它也可以防止网络性能的下降。这些命令被设置为缺省值。
关闭如下参数可以防止黑客对服务器IP地址的攻击
[bash]
sysctl -w net.ipv4.conf.eth0.accept_source_route=0
sysctl -w net.ipv4.conf.lo.accept_source_route=0
sysctl -w net.ipv4.conf.default.accept_source_route=0
sysctl -w net.ipv4.conf.all.accept_source_route=0
[/bash]

以下命令使服务器忽略来自被列入网关的服务器的重定向。因重定向可以被用来进行攻击,所以我们只接受有可靠来源的重定向
[bash]
sysctl -w net.ipv4.conf.eth0.secure_redirects=1
sysctl -w net.ipv4.conf.lo.secure_redirects=1
sysctl -w net.ipv4.conf.default.secure_redirects=1
sysctl -w net.ipv4.conf.all.secure_redirects=1
[/bash]

另外,你可以配置接受或拒绝任何ICMP重定向。ICMP重定向是器传输信息的机制。比如,当网关接收到来自所接网络主机的Internet数据报时,网关可以发送重定向信息到一台主机。网关检查路由表获得下一个网关的地址,第二个网关将数据报路由到目标网络。关闭这些重定向得命令如下:
[bash]
sysctl -w net.ipv4.conf.eth0.accept_redirects=0
sysctl -w net.ipv4.conf.lo.accept_redirects=0
sysctl -w net.ipv4.conf.default.accept_redirects=0
sysctl -w net.ipv4.conf.all.accept_redirects=0
[/bash]

如果这个服务器不是一台路由器,那么它不会发送重定向,所以可以关闭该功能:
[bash]
sysctl -w net.ipv4.conf.eth0.send_redirects=0
sysctl -w net.ipv4.conf.lo.send_redirects=0
sysctl -w net.ipv4.conf.default.send_redirects=0
sysctl -w net.ipv4.conf.all.send_redirects=0
[/bash]

配置服务器拒绝接受广播风暴或者smurf 攻击attacks:
[bash]sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1[/bash]

忽略所有icmp包或者pings:
[bash]sysctl -w net.ipv4.icmp_echo_ignore_all=1[/bash]

有些路由器针对广播祯发送无效的回应,每个都产生警告并在内核产生日志。这些回应可以被忽略:
[bash]sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1[/bash]

下边的命令用来对连接数量非常大的服务器进行调优。
表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0
[bash]net.ipv4.tcp_tw_reuse = 1[/bash]

表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0
[bash]net.ipv4.tcp_tw_recycle = 1[/bash]

tcp_fin_timeout

默认值是 60
对于本端断开的socket连接,TCP保持在FIN_WAIT_2状态的时间。对方可能会断开连接或一直不结束连接或不可预料的进程死亡。默认值为 60 秒。过去在2.2版本的内核中是 180 秒。您可以设置该值﹐但需要注意﹐如果您的机器为负载很重的web服务器﹐您可能要冒内存被大量无效数据报填满的风险﹐FIN-WAIT-2 sockets 的危险性低于 FIN-WAIT-1 ﹐因为它们最多只吃 1.5K 的内存﹐但是它们存在时间更长。另外参考 tcp_max_orphans。
CLOSE_WAIT状态的生成原因
如果服务器程序APACHE处于CLOSE_WAIT状态的话,说明套接字是被动关闭的!
假设CLIENT端主动断掉当前连接,那么双方关闭这个TCP连接共需要四个packet:
Client ---> FIN ---> Server
Client <--- ACK <--- Server 这时候Client端处于FIN_WAIT_2状态;而Server 程序处于CLOSE_WAIT状态。 Client <--- FIN <-- Server 这时Server 发送FIN给Client,Server 就置为LAST_ACK状态。 Client ---> ACK ---> Server-
Client回应了ACK,那么Server 的套接字才会真正置为CLOSED状态。
Server 程序处于CLOSE_WAIT状态,而不是LAST_ACK状态,说明还没有发FIN给Client,那么可能是在关闭连接之前还有许多数据要发送或者其他事要做,导致没有发这个FIN packet。
通常来说,一个CLOSE_WAIT会维持至少2个小时的时间。如果有个流氓特地写了个程序,给你造成一堆的CLOSE_WAIT,消耗资源,那么通常是等不到释放那一刻,系统就已经解决崩溃了。
改变这个值的前要经过认真的监测,避免因为死套接字造成内存溢出。
[bash]sysctl -w net.ipv4.tcp_fin_timeout=30[/bash]

对于所有的队列(即系统),设置最大系统发送缓存(wmem) 和接收缓存(rmem)到8MB
[bash]
sysctl -w net.ipv4.core.wmem_max=8388608
sysctl -w net.ipv4.core.rmem_max=8388608
[/bash]

使用如下命令调整tcp发送和接收缓存。该命令设定了三个值:最小值、初始值和最大值:
[bash]
sysctl -w net.ipv4.tcp_rmem="4096 87380 8388608"
sysclt -w net.ipv4.tcp.wmem="4096 87380 8388608"
[/bash]

第三个值必须小于或等于wmem_max和rmem_max。
当服务器负载繁重或者是有很多客户端都是超长延时的连接故障,可能会导致half-open连接数量的增加。这对于Web服务器很来讲很平常,尤其有很多拨号客户时。这些half-open连接保存在 backlog(积压) connections 队列中。
将这个值最少设置为4096 (缺省为1024)。 即便是服务器不接收这类连接,设置这个值还能防止受到denial-of-service (syn-flood)的攻击
[bash]sysctl -w net.ipv4.tcp_max_syn_backlog=4096[/bash]

设置ipfrag参数,尤其是NFS和Samba服务器。这里,我们可以设置用于重新组合IP碎片的最大、最小内存。当ipfrag_high_thresh值被指派,碎片会被丢弃直到达到ipfrag_low_thres值。
当TCP数据包传输发生错误时,开始碎片整理。有效的数据包保留在内存,同时损坏的数据包被转发。例如,设置可用内存范围从256 MB到384 MB
[bash]
sysctl -w net.ipv4.ipfrag_low_thresh=262144
sysctl -w net.ipv4.ipfrag_high_thresh=393216
[/bash]

网络安全设置

防止TCP SYN Flood 攻击
TCP SYN Flood是一种常见,而且有效的远端(远程)拒绝服务(Denial of Service)攻击方式,它透过一定的操作破坏TCP三次握手建立正常连接,占用并耗费系统资源,使得提供TCP服务的主机系统无法正常工作。由於TCP SYN Flood是透过网路底层对服务器Server进行攻击的,它可以在任意改变自己的网路IP地址的同时,不被网路上的其他设备所识别,这样就给防范网路犯罪部门追查犯罪来源造成很大的困难。
系统检查

一般情况下,可以一些简单步骤进行检查,来判断系统是否正在遭受TCP SYN Flood攻击
1、服务端无法提供正常的TCP服务。连接请求被拒绝或超时
2、透过 netstat -an 命令检查系统,发现有大量的SYN_RECV连接状态

iptables的设置
防止同步包洪水(Sync Flood)
[bash]iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT[/bash]

也有人写作
[bash]iptables -A INPUT -p tcp --syn -m limit --limit 1/s -j ACCEPT[/bash]

–limit 1/s 限制syn并发数每秒1次,可以根据自己的需要修改

防止各种端口扫描
[bash]iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT[/bash]

Ping洪水攻击(Ping of Death)
[bash]iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT[/bash]

内存子系统的调优

内存子系统的调优不是很容易,需要不停地监测来保证内存的改变不会对服务器的其他子系统造成负面影响。如果要改变虚拟内存参数(在/proc/sys/vm),建议每次只改变一个参数然后监测效果。
对与虚拟内存的调整包括以下几个项目:
配置Linux内核如何更新dirty buffers到磁盘
磁盘缓冲区用于暂存磁盘的数据。相对于内存来讲,磁盘缓冲区的速度很慢。因此,如果服务器使用这类内存,性能会成问题。当缓冲区内的数据完全dirty,使用:
[bash]sysctl -w vm.bdflush="30 500 0 0 500 3000 60 20 0"[/bash]

vm.bdflush有9个参数,但是建议只改变其中的3个:
1 nfract, 为排队写入磁盘前,bdflush daemon允许的缓冲区最大百分比
2 ndirty, 为bdflush即刻写的最大缓冲区的值。如果这个值很大,bdflush需要更多的时间完成磁盘的数据更新。
7 nfract_sync, 发生同步前,缓冲区变dirty的最大百分比

配置kswapd daemon,指定Linux的内存页数量
[bash]sysctl -w vm.kswapd="1024 32 64"[/bash]

三个参数的描述如下:
– tries_base 相当于内核每次所的“页”的数量的四倍。对于有很多交换信息的系统,增加这个值可以改进性能。
– tries_min 是每次kswapd swaps出去的pages的最小数量。
– swap_cluster 是kswapd 即刻写如的pages数量。数值小,会提高磁盘I/O的性能;数值大可能也会对请求队列产生负面影响。

如果要对这些参数进行改动,请使用工具vmstat检查对性能的影响。其它可以改进性能的虚拟内存参数为:
_ buffermem
_ freepages
_ overcommit_memory
_ page-cluster
_ pagecache
_ pagetable_cache

文件子系统的调优

ulimit -a 用来显示当前的各种用户进程限制。
Linux对于每个用户,系统限制其最大进程数。为提高性能,可以根据设备资源情况,设置各linux 用户的最大进程数,下面我把某linux用户的最大进程数设为10000个:
[bash]ulimit -u 10000[/bash]

对于需要做许多 socket 连接并使它们处于打开状态的 Java 应用程序而言,最好通过使用 ulimit -n xx 修改每个进程可打开的文件数,缺省值是 1024。
ulimit -n 4096 将每个进程可以打开的文件数目加大到4096,缺省为1024
其他建议设置成无限制(unlimited)的一些重要设置是:
数据段长度:ulimit -d unlimited
最大内存大小:ulimit -m unlimited
堆栈大小:ulimit -s unlimited
CPU 时间:ulimit -t unlimited
虚拟内存:ulimit -v unlimited
暂时地,适用于通过 ulimit 命令登录 shell 会话期间。
永久地,通过将一个相应的 ulimit 语句添加到由登录 shell 读取的文件中,即特定于 shell 的用户资源文件,如:
1)、解除 Linux 系统的最大进程数和最大文件打开数限制:
vi /etc/security/limits.conf
# 添加如下的行
[bash]
* soft noproc 11000
* hard noproc 11000
* soft nofile 4100
* hard nofile 4100
[/bash]
说明:* 代表针对所有用户
noproc 是代表最大进程数
nofile 是代表最大文件打开数
2)、让 SSH 接受 Login 程式的登入,方便在 ssh 客户端查看 ulimit -a 资源限制:
a、vi /etc/ssh/sshd_config
把 UserLogin 的值改为 yes,并把 # 注释去掉
b、重启 sshd 服务:
/etc/init.d/sshd restart
3)、修改所有 linux 用户的环境变量文件:
[bash]
vi /etc/profile
ulimit -u 10000
ulimit -n 4096
ulimit -d unlimited
ulimit -m unlimited
ulimit -s unlimited
ulimit -t unlimited
ulimit -v unlimited
[/bash]

有时候在程序里面需要打开多个文件,进行分析,系统一般默认数量是1024,(用ulimit -a可以看到)对于正常使用是够了,但是对于程序来讲,就太少了。
修改2个文件。
1.vi /etc/security/limits.conf
加上:
[bash]
* soft nofile 8192
* hard nofile 20480
[/bash]

2./etc/pam.d/login
[bash]session required /lib/security/pam_limits.so[/bash]

另外确保/etc/pam.d/system-auth文件有下面内容
[bash]session required /lib/security/$ISA/pam_limits.so[/bash]

这一行确保系统会执行这个限制。

3.一般用户的.bash_profile
[bash]ulimit -n 1024[/bash]

重新登陆ok

优化步骤:

修改/etc/profile文件,加入:
[bash]
ulimit -u 10240
ulimit -n 4096
ulimit -d unlimited
ulimit -m unlimited
ulimit -s unlimited
ulimit -t unlimited
ulimit -v unlimited
[/bash]

修改/etc/rc.d/rc.local,加入:
[bash]
echo ‘999999′ > /proc/sys/fs/file-max
echo ‘999999′ > /proc/sys/fs/inode-max
[/bash]

(1G内存值修改成:65535 2G内存值修改成:131072 4G内存值修改成:262144)
修改/etc/sysctl.conf文件,加入:
[bash]
net.core.rmem_default = 8388608
net.core.rmem_max = 8388608
net.core.wmem_default = 8388608
net.core.wmem_max = 8388608
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_sack =1
net.ipv4.tcp_window_scaling = 1
net.core.netdev_max_backlog=3000
[/bash]

#Modify i-node
[bash]
sys.fs.file-max= 65535
sys.fs.inode-max= 65535
[/bash]

#Set System Memory
[bash]
vm.bdflush="30 500 0 0 500 3000 60 20 0"
vm.kswapd="1024 32 64"
[/bash]

#Disable HackAttack!
[bash]
net.ipv4.conf.eth0.accept_source_route=0
net.ipv4.conf.lo.accept_source_route=0
net.ipv4.conf.default.accept_source_route=0
net.ipv4.conf.all.accept_source_route=0
net.ipv4.conf.lo.accept_redirects=0
net.ipv4.conf.all.accept_redirects=0
net.ipv4.conf.eth0.accept_redirects=0
net.ipv4.conf.default.accept_redirects=0
net.ipv4.conf.lo.secure_redirects=0
net.ipv4.conf.all.secure_redirects=0
net.ipv4.conf.eth0.secure_redirects=0
net.ipv4.conf.default.secure_redirects=0
net.ipv4.conf.eth0.send_redirects=0
net.ipv4.conf.lo.send_redirects=0
net.ipv4.conf.default.send_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.tcp_syncookies=1
net.ipv4.icmp_echo_ignore_broadcasts=1
net.ipv4.icmp_ignore_bogus_error_responses=1
[/bash]

#Web Servers
[bash]
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_keepalive_time=1800
net.ipv4.core.wmem_max=16777216
net.ipv4.core.rmem_max=16777216
net.ipv4.tcp_rmem="4096 87380 8388608"
net.ipv4.tcp.wmem="4096 87380 8388608"
net.ipv4.tcp_max_syn_backlog=8192
[/bash]

防火墙安全:
[bash]iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT[/bash]
也有人写作
[bash]iptables -A INPUT -p tcp --syn -m limit --limit 1/s -j ACCEPT[/bash]
–limit 1/s 限制syn并发数每秒1次,可以根据自己的需要修改

防止各种端口扫描
[bash]iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT[/bash]

Ping洪水攻击(Ping of Death)
[bash]iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT[/bash]
备注说明:(相对比较激进的网络参数调整)

# Use TCP syncookies when needed
[bash]net.ipv4.tcp_syncookies = 1[/bash]

# Enable TCP window scaling
[bash]net.ipv4.tcp_window_scaling = 1[/bash]

# Increase TCP max buffer size
[bash]
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
[/bash]

# Increase Linux autotuning TCP buffer limits
[bash]
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 65536 8388608
[/bash]

# Increase number of ports available
[bash]net.ipv4.ip_local_port_range = 1024 65000[/bash]

Linux系统与性能监控
http://kerrigan.sinaapp.com/post-7.html

性能调优攻略
http://coolshell.cn/articles/7490.html

Linux系统下的DDOS攻击防范
http://hi.baidu.com/moneyxml/item/6359b5fccd11950dd89e7212

Linux内核参数调整说明
http://blog.csdn.net/radkitty/article/details/3009522

调整内核网络参数提高Linux系统安全
http://linux.ccidnet.com/art/302/20070111/998987_1.html

linux内核参数更改(整理)
http://space.doit.com.cn/54383/viewspace-7077.html

SYN Flood攻击、SYN Cookie防御和Linux/FreeBSD的内核参数修改
http://www.path8.net/tn/archives/5904

除非注明,文章皆由( csz )原创,转载请标明本文地址
本文地址: http://www.cszhi.com/20140127/linux-performance.html

标签: 性能调优

添加新评论