评析Linux多层面优化策略
2020-12-31河南刘建臣
■ 河南 刘建臣
优化设置Linux内核参数
在使用Linux时,必然要和系统内核进行交互,在用户和内核之间其实是通过“/proc”这个虚拟文件系统进行联系的。在其中提供了一些虚拟文件,当用户对其进行读写时,就可以与内核进行交互。当然,这些虚拟文件都是动态建立的。因为其活动在内存中,因此如果使用普通的方法对其进行查看,是无法显示其真实大小的。
例如在“/proc/sys/kernel”目录中保存和内核相关的参数,例如在CentOS 7.X中执行“echo “1” >/proc/sys/net/ipv4/ip_forward”命令,可以打开代理转发功能。执行“sysctl kernel.msgmnb”命令,可以显示单个队列中允许的最大字节长度。执行“sysctl-w kernel.msgmnb=40960”命令,可以对该参数进行修改。但是,如果重启系统后,进行的修改就会消失。为此可以执行诸如“vim/etc/sysctl.conf”命令,在该文件中添加“sysctl kernel.msgmnb=40960”行,保存后执行“sysctl -p”命令,可以让修改操作立即生效。
执行“echo 1 >/proc/sys/kernel/panic”命令,设置当内核出错时,可以自动重启。执行“echo 196608>/proc/sys/kernel/pid_max”命令,可以设置进程数量最大值。执行“echo 1>/proc/sys/kernel/ctrlalt-del”命令,可以禁止按下Ctrl+Alt+Delete组合键时系统重启。执行“echo"core.%e.%p " >/proc/sys/kernel/core_pattern”命令,设置Core文件保存位置信息。
优化文件系统性能
在“/proc/sys/fs”目录中保存和文件系统相关的参数。例如,执行“echo"10485750">/proc/sys/fs/file-max”命令,可以设置分配的文件句柄的最大数目。执行“echo "8192000">/proc/sys/fs/inotify/max_user_watches”命令,可以设置每个Real User ID可创建的inotify instatnces的数量上限。磁盘一般包括机械硬盘和固态硬盘,实际上,不管何种形式的磁盘,其随机I/O的速度都要比顺序I/O慢得多。
对于顺序I/O来说,会采取预读取的方式,来降低I/O请求次数,进而优化性能。在Linux中如果出现大量读请求,默认的请求队列因为长度不够,可能无法应对。为此可以动态调整请求队列数来解决问题。
为了提高预读取性能,可以对“/sys/block/sdb/queue/read_ahead_kb”参数进行适当调整,其默认值为128字节。当不同的进程在请求I/O资源时,系统就需要对其进行合理的调度。
对于Deadline调度算法来说,通过降低性能而获得更短的等待时间,提供了最小的读取延迟和较好的吞吐量,比较适用于数据库服务器等读取量较大的环境。对于固态磁盘,以及RAID磁盘阵列来说,比较适合使用电梯调度算法。
对于CFQ调度算法来说,使用了QoS策略为所有任务分配等量的带宽,实现了较低的延迟,结合了以上两个算法的优点,对于多用户环境比较适用。可以根据实际情况,针对不同的磁盘设置合适的算法。例如执行“echo'cfq'>/sys/block/sdb/queue/scheduler”命令,将指定的磁盘设定为CFQ调度算法。
对于固态硬盘来说,使用Trim技术可以大幅提高数据读写性能。例如,执行“lsblk-D/dev/sdb”命令,可以检测SSD磁盘是否支持Trim功能。如果在返回信息中的“DISC-GRAN”和“DISC-MAX”列中为非零值,说明其支持Trim功能。注意,只有Ext4和XFS格式支持Trim功能。
执行“mount -t ext4-o discard/dev/sdb1/mnt”命令,可以在指定的分区上启用Trim功能,还可以执行“/usr/sbin/fstrim-a”命令,自动检测硬盘是否支持TRIM功能,并在已挂载文件系统上执行TRIM功能。
对于CentOS7.X中已经使用了性能更加优异的XFS文件系统,在对磁盘进行格式化时,可以同步进行优化操作。
优化网络连接性能
在“/proc/sys/net”中保存和网络相关的参数,对于Web服务器来说,合理的配置这些参数,对于有效的提高系统的性能。
例如,执行“echo 2 >/proc/sys/net/ipv4/tcp_syn_retries”命令,可以设置当内核要2个SYN连接请求后才才放弃一个新建连接。执行“echo 300>/proc/sys/net/ipv4/tcp_keepalive_time”命令,可以设置TCP发送keepalive消息的频度。执行“echo 1 >/proc/sys/net/ipv4/tcp_orphan_retries”命令,可以重试后放弃Socket连接。
执行“echo 1 >/proc/s ys/net/ipv4/ tcp_syncook ies”命令,可以启用SYN Cookies功能,可以有效防御SYN攻击。执行“echo 8192>/proc/sys/net/ipv4/tcp_max_syn_backlog”命令,将SYN队列长度设置为8192,可以接受更多的网络连接。
执行“echo 2 >//proc/sys/net/ipv4/tcp_synack_retries”命令,将SYN+ACK报文重试次数设置为2。
执行“echo 1 >/proc/sys/net/ipv4/ tcp_tw_recycle”命令,启用TCP连接中TIME-WAIT Sockets快速回收功能。
执行“netstat -n | aw k '/^tcp/ {++state[$NF]};END {for(key in state) p rint key," ",state[key]}'”,“netstat -n | awk'/^tcp/ {++arr[$NF]};END{for(k in arr) print k," ",arr[k]}'”等命令,可以查看系统的TIME-WAIT状态信息。
执行“echo 1 >/proc/sys/net/ipv4/tcp_tw_reuse”命令,可以允许将TIME-WAIT sockets重新用于新的TCP连接。当然,这必须同时开启TIME-WAIT Sockets快速回收功能。
执行“cho 15 >/proc/sys/net/ipv4/tcp_fin_timeout”命令,设置处于TIME_WAIT状态的连接在回收前必须等待的最小时间。执行“echo 5>/proc/sys/net/ipv4/ tcp_keepalive_probes”命令,设置超时前的等待次数。
执行“echo 3000>/pro c/sys/net/ipv4/ netdev_max_backlog”命令,设置每个网络接口接收数据包的速率大于内核处理这些包的速率快时,允许送到队列的数据包的最大数目。执行“echo 16777216>/proc/sys/net/core/rmem_max”,“echo 16777216>/proc/sys/net/core/wmem_max”命令,设置接收/发送套接字缓冲区大小的最大值,单位为字节。
执行“echo "4096 87380 16777216">/proc/sys/net/ipv4/tcp_rmem”,“echo"4096 65536 16777216">/proc/sys/net/ipv4/tcp_rmem”命令,分别设置内核自动对Socket缓冲区进行读取/写入的最小值,默认值和最大值。执行“echo 4096 >/proc/sys/net/core/somaxconn”命令,可以设置Socket监听的队列上限。
优化内存管理机制
对内存设置进行优化,必须搞清楚Buffer(缓冲)和Cache(缓存)的关系。Cached工作在CPU与内存之间的层面,经常被应用到磁盘I/O请求上。Buffer工作在内存与磁盘之间的层面。Cache将CPU读取过的数据保存起来,便于CPU下次需要时快速读取,而不必重复从磁盘中读取这些数据。如果Cache中没有搜索到数据,系统才会从磁盘中读取。而且系统会根据CPU读取的频率,将最频繁的数据存放到Cache中最容易找到的位置。
对于Buffer来说,存储的是需要写入磁盘的数据。Buffe是针对不同的进程进行分配的。在Linux中Cache的读写是分别进行的。
一方面磁盘数据会被读取到Page Cache进行缓存,程序要会从中直接读取数据读取数据。
另一方面当刷新Page Cache的数据时,Page Cache会将其提交给Buffer Cache,由其将所有数据定期写入到磁盘中。对于Page Cache来说,是文件系统层级的缓存。对于Buffer Cache来说,是用于磁盘等块设备的缓冲。
例如,执行Sync命令,可以手工将Buffer Cache的数据写入磁盘。当读取文件时,系统会首先在Page Cache中查找,当执行时系统只是将数据暂写入Page Cache中,并将该页置上dirty标志,这些数据会被定期批量保存到文件系统中。
在“/proc/sys/vm”目录中保存和内存设置相关的参数,对于Page Cache进行优化,主要包含“vm.dirty_background_ratio”和“vm.dirty_ratio”参数。
例如,执行“echo 5>/proc/sys/vm/dirty_background_ratio”命令,设置当文件系统缓存脏数据数量达到系统内存5%时,就会触发Pdflush等后台回写进程运行。
执行“echo 10 >/proc/sys/vm/dirty_ratio”命令,设置当文件系统缓存脏数据数量达到系统内存10%时,必须开始处理缓存脏页,其要大于或者等于前者的数值,因为此时脏页数量已经比较多,为了避免数据丢失需要将一定脏页写入磁盘。
如果需要立即回收Cache,可以执行“echo 1 >/proc/sys/vm/drop_caches”命令,释放Page Cache。
执行“sync”命令,将缓存写入磁盘。执行“echo 3>/proc/sys/vm/drop_cache s”命令,可以释放文件节点缓存和目录项缓存。
执行“echo 3 >/proc/sys/vm/drop_caches”命令,可以释放以上所有缓存项目。在“/proc/sys/vm/dirty_expire_centisecs”参数中设置脏数据在内存中驻留时间,如果超过超过该值的话,Pdflush进程在下一次将把这些数据写回磁盘。在“/proc/sys/vm/dirty_writeback_centisecs”参数中设置新进程pdflush的运行间隔,该进程用于刷新内核的脏数据。
在“/proc/sys/vm/vfs_cache_pressure”参数中内核回收用于directory和inode cache内存的倾向。在“/proc/sys/vm/min_free_kbytes”参数中设置强制Linux VM最低保留多少空闲内存。
在“/proc/sys/vm/over commit_memory”参数中设置内存分配策略,如果为0表示当应用程序申请内存时,如果有足够的可用内存则申请允许,否则内存申请失败,并把错误返回给应用进程。如果为1表示内核允许分配所有的物理内存,如果为2表示内核允许分配超过所有物理内存和交换空间总和的内存。
在“/proc/sys/vm/panic_on_oom”参数的值如果为0,表示当内存耗尽时内核会触发OOM killer清除最耗内存的进程。
如果设置为1表示在OOM时系统会Panic。使用交换分区,可以缓解内存不足的问题。