一、内核参数文档的查看
1. 在Linux系统中所有的内核参数都可以查询到,只需要安装官方安装包kernel-doc,先学习下内核参数帮助文档的使用
安装kernel-doc
1 | [root@student02 ~]# yum -y install kernel-doc |
所有的内核参数都可以查询文档
1 | [root@student02 ~]# ls /usr/share/doc/kernel-doc-3.10.0/Documentation/ |
可以查询vm.drop_caches参数的文档,在文件vm.txt的182行记录echo 3 可以清空内存里面的缓存
1 | [root@student02 ~]# grep -irn --color=auto vm.drop_caches /usr/share/doc/kernel-doc-3.10.0/Documentation/ |
二、性能调优工具
1. tuned
安装tuned启动服务
1 | [root@student02 ~]# yum -y install tuned |
查看系统中对于不同应用场景的调优方案
1 | [root@student02 ~]# tuned-adm list |
查看当前的调优方案
1 | [root@student02 ~]# tuned-adm active |
balanced
:一般的非专业的调优配置
desktop
:优化桌面使用环境
latency-performance
:以增加功耗为代价优化确定的性能
network-latency
:以增加功耗为代价优化确定的性能,重点是低延迟网络性能
network-throughput
:优化网络吞吐量,一般只需要用在旧的CPU和40G+的网络中
powersave
:低功率的优化
throughput-performance
:广泛适用的调整,可在各种常见服务器工作负载下提供出色的性能,这是RHEL7的默认配置文件。
virtual-guest
:优化运行在主机内部的虚拟机
virtual-host
:优化运行KVM虚拟机的主机
使用高性能的配置策略
1 | [root@student02 ~]# tuned-adm profile throughput-performance |
tuned调优的配置文件,也可以自己添加一个目录,修改成自己适合的配置
1 | [root@student02 ~]# ls /usr/lib/tuned/ |
2. limits
limits的配置文件
1 | [root@student02 ~]# vim /etc/security/limits.conf |
硬限制用户只能打开2048个文件
1 | [root@student02 ~]# vim /etc/security/limits.conf |
硬限制用户只能使用10M虚拟内存
1 | [root@student02 ~]# vim /etc/security/limits.conf |
查看limits对我的所有限制
1 | [root@student02 ~]# ulimit -a |
软限制用户只能使用100M虚拟内存,用户可以在硬限制范围内修改软限制
1 | [root@student02 ~]# vim /etc/security/limits.conf |
3. cgroup
安装cgroup启动服务
1 | [root@student02 ~]# yum -y install libcgroup-tools |
启动服务后会产生一个cgroup的临时目录,查看对各种资源限制的配置,每个目录里面还有很多限制子选项
1 | [root@student02 ~]# df -h |grep cgroup |
查看参数名,cgconfig.conf中创建一个组test,限制磁盘读bps为1M,内存使用256M
1 | [root@student02 ~]# ll /dev/sda |
cgrules.conf中配置策略,用户student的blkio和memory应用test组策略的限制
1 | [root@student02 ~]# vim /etc/cgrules.conf |
也可以具体限制到命令
1 | [root@student02 ~]# vim /etc/cgrules.conf |
三、系统状态监控工具
1. iostat命令,监控系统设备的IO负载情况
不接参数,显示系统启动以来的i/o状态的平均结果
1 | [root@student02 ~]# iostat |
%user
:显示在用户级别(application)运行使用 CPU 总时间的百分比。
%nice
:显示在用户级别,用于nice操作,所占用 CPU 总时间的百分比。
%system
:在核心级别(kernel)运行所使用 CPU 总时间的百分比。
%iowait
:显示用于等待I/O操作占用 CPU 总时间的百分比。
%steal
:管理程序(hypervisor)为另一个虚拟进程提供服务而等待虚拟 CPU 的百分比。
%idle
:显示 CPU 空闲时间占用 CPU 总时间的百分比。
- 若 %iowait 的值过高,表示硬盘存在I/O瓶颈
- 若 %idle 的值高但系统响应慢时,有可能是 CPU 等待分配内存,此时应加大内存容量
- 若 %idle 的值持续低于1,则系统的 CPU处理能力相对较低,表明系统中最需要解决的资源是 CPU 。
1 | [root@student02 ~]# iostat 1 #1秒钟显示一次,一直监控 |
Device
:磁盘设备
tps
:多少I/O请求数/s
kB_read/s
:读多少block/s
kB_wrtn/s
:写多少block/s
kB_read
:一共读block
kB_wrtn
:一共写block
1 | [root@student02 ~]# echo "(10909+196763)*512/1024/1024" |bc |
kB_wrtn/s除以tps就可以得到每个I/O的大小,可以通过I/O大小判断组建哪种RAID,RAID5适合顺序的大I/O,RAID10适合随机的小I/
2. sar命令,对系统的活动进行报告
参数介绍:
-A
:所有报告的总和
-u
:输出CPU使用情况的统计信息
-v
:输出inode、文件和其他内核表的统计信息
-d
:输出每一个块设备的活动信息
-r
:输出内存和交换空间的统计信息
-b
:显示I/O和传送速率的统计信息
-a
:文件读写情况
-c
:输出进程统计信息,每秒创建的进程数
-R
:输出内存页面的统计信息
-y
:终端设备活动情况
-w
:输出系统交换活动信息
查看CPU负载信息
1 | [root@student02 ~]# sar -u 1 10 |
%user
:显示在用户级别(application)运行使用 CPU 总时间的百分比。
%nice
:显示在用户级别,用于nice操作,所占用 CPU 总时间的百分比。
%system
:在核心级别(kernel)运行所使用 CPU 总时间的百分比。
%iowait
:显示用于等待I/O操作占用 CPU 总时间的百分比。
%steal
:管理程序(hypervisor)为另一个虚拟进程提供服务而等待虚拟 CPU 的百分比。
%idle
:显示 CPU 空闲时间占用 CPU 总时间的百分比。
- 若 %iowait 的值过高,表示硬盘存在I/O瓶颈
- 若 %idle 的值高但系统响应慢时,有可能是 CPU 等待分配内存,此时应加大内存容量
- 若 %idle 的值持续低于1,则系统的 CPU处理能力相对较低,表明系统中最需要解决的资源是 CPU 。
以24小时制来显示时间
1 | [root@student02 ~]# alias sar='LANG=C sar' |
内存和交换空间监控
1 | [root@student02 ~]# sar -r 1 10 |
kbmemfree
:这个值和free命令中的free值基本一致,所以它不包括buffer和cache的空间.
kbmemused
:这个值和free命令中的used值基本一致,所以它包括buffer和cache的空间.
%memused
:这个值是kbmemused和内存总量(不包括swap)的一个百分比.
kbbuffers和kbcached
:这两个值就是free命令中的buffer和cache.
kbcommit
:保证当前系统所需要的内存,即为了确保不溢出而需要的内存(RAM+swap).
%commit
:这个值是kbcommit与内存总量(包括swap)的一个百分比.
1 | [root@student02 ~]# sar -d 1 10 #显示磁盘负载信息以及10s的平均负载 |
3. vmstat命令,服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况
1 | [root@student02 ~]# vmstat 1 10 |
r
:表示运行队列,多少个进程分配到cpu,这个值超过了CPU数目就会出现CPU瓶颈,如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高。
b
:表示阻塞的进程
swpd
: 虚拟内存已使用的大小,如果大于0,表示你的机器物理内存不足了。
free
:空闲的物理内存的大小。
buff
:存储文件列表,权限等的缓存。
cache
:文件内容的缓存。
si
:每秒从磁盘读入虚拟内存的大小。
so
:每秒虚拟内存写入磁盘的大小。
bi
:块设备每秒接收的块数量。
bo
:块设备每秒发送的块数量,读取文件,bo就会大于0。
in
:每秒CPU的中断次数,包括时间中断。
cs
:CPU每秒上下文切换次数,调用系统函数,线程的切换要进行上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,web服务器中需要调节这个值最小。
us
:用户CPU时间
sy
:系统CPU时间
id
:空闲CPU时间
wt
:I/O等待CPU时间
4. free
free命令是linux的一个入门级命令,显示的是一个比较总述性的信息,如下:
1 | [root@student02 ~]# free -m |
比如上面的输出中,我们大致可以看到我总内存为1G(995,其中hardward和firmware在启动时会预先占用一点)。其中已使用874M ,其中可用121M,buffers和cached加用的量为105M + 249M ,这里需要注意的是平时我们在查看时,一般会以第二行的结果为准,即实际可用477M,已用518M。为什么这样说?因为buffers和cached是为了加快运算速度,会预占用一部分内存,可以理解为缓存的概念。由于这部分不是本篇的重点,想深究的可以找谷歌。这部分内存可以通过如下的命令进行回收:
1 | [root@student02 ~]# sysctl -w vm.drop_caches=3 |
在有业务运行的情况下,强烈不建议这样操作,因为可能会造成数据丢失。
5. top
即然内存被使用,到底被谁占去了呢?可以借助强大的top查看。
1 | [root@student02 ~]# top |
在top下我们输入大M就可以按内存使用率排序。上面可以看到我内存主要被hhvm进程占用掉了,占比总内存的34.3% 。可以看到,实际上top上面也有free的功能,对memory会有概述性报告的。其中RES是我们要关注的项,即实际该进程占用的内存量,基本上这样我们就定位到内存用到那去了。现网中经常还需要一种情况,top看到的所有进程的RES使用都不大,而内存一下子少了几十G,这个怎么破呢?看下面。
6. /proc/meminfo
meminfo文件显示出的也是内存的概述性信息,只不过其比free -m的结果要更详细,如下:
1 | [root@361way ~]# cat /proc/meminfo |
7. 缓存命中率cache-hit
安装valgrind
1 | [root@student02 ~]# yum -y install valgrind |
查看命令或者脚本的cache-miss
1 | [root@student02 ~]# valgrind --tool=cachegrind ls |
8. strace用来跟踪一个进程的系统调用或信号产生的情况
查看复制文件的状态跟踪
1 | [root@student02 ~]# strace -fc cp /etc/passwd /tmp/ |
可以具体到查看命令打开了什么文件
1 | [root@student02 ~]# strace -e open cp /etc/passwd /tmp/ |
9. ltrace用来跟踪进程调用库函数的情况
查看命令对系统和库的调用
1 | [root@student02 ~]# ltrace -Sfc cp /etc/passwd /tmp/ |
四、文件系统的调优
1. tune2fs
查看文件系统信息
1 | [root@student02 ~]# tune2fs -l /dev/sda3 |
df查看分区有一部分空间(976M-2.6M-907M=66.4M)看不到
1 | [root@student02 ~]# df -h |grep sda3 |
Reserved GDT blocks
:每个分区5%的block会被保留
修改分区保留比例为1%
1 | [root@student02 ~]# tune2fs -m 10 /dev/sda3 |
修改磁盘的UUID
1 | [root@student02 ~]# blkid |grep sda3 |
2. dumpe2fs,查看文件系统结构
1 | [root@student02 ~]# dumpe2fs /dev/sda3 |
Journal size
:日志区大小
Group x
:文件系统会把block分成很多个group,每个group的大小为32768个block,当文件系统在使用的时候每个group都是平均使用的,不会使用完,当已经写入的文件需要扩大的时候可以就文件当前的group上面分配空间,让文件尽可能连续,不必到距离很远的block分配空间,可以提升文件读取性能。
superblock
:superblock在第0个group上,第1、3、 5、7、9个group上面有superblock的备份
Group descriptors
:每个group的第一个block存放group的描述信息
Reserved GDT blocks
:每个group有127个保留的block
Block bitmap
:记录block的位图区
Inode bitmap
:记录inode索引文件的位图区
Inode table
:inode索引表
Free blocks
:未使用的block
Free inodes
:未使用的inode
3. 修复文件系统
破坏超级快和block保留区,挂载失败
1 | [root@student02 ~]# dd if=/dev/zero of=/dev/sda3 bs=1K count=516 |
用fsck修复文件系统
1 | [root@student02 ~]# fsck -v /dev/sda3 |
有的情况下fsck修复不了可以使用e2fsck指定超级快修复
1 | [root@student02 ~]# e2fsck -b 98304 /dev/sda3 |
4. 非日志型文件系统与日志型文件系统
非日志型文件系统:fat32、ext2
文件系统无日志区,文件写入过程:
1 | graph LR |
在非日志型文件系统中,对文件系统实施一个写操作,内核会首先修改对应的元数据,然后修改数据块。如果在写入元数据时,文件系统发生崩溃或某种故障,那么数据的一致性将会遭到破坏。fsck命令可以在下次重启时检查所有的元数据并修复数据一致性,但是如果文件系统非常大,或者系统运行关键业务不允许停机,使用非日志型文件系统的风险会非常高。
日志型文件系统:ntfs、ext3、ext4、xfs、jfs
文件系统有日志区,文件写入过程:
1 | graph LR |
日志型文件系统的区别在于,在进行对文件系统写数据之前,写将数据写到「日志区」,然后再写入文件系统,在写入文件系统之后删除日志。日志区可以在文件系统内部也可以在文件系统外部。日志区的数据称作文件系统日志,这些数据包含了修改了的元数据,也可能包含将要修改的数据。写日志也会带来一定的额外开销。
查看文件系统的日志区大小
1 | [root@student02 ~]# dumpe2fs /dev/sda3 |grep "Journal size" |
5. 内部日志区和外部日志区
内部日志区,日志区在当前文件系统,会对文件系统进行两次索引信息写入
外部日志区,单独一个文件系统做日志区,减少访问次数,减少服务时间
创建外部日志区
1 | [root@student02 ~]# umount /dev/sda3 #先卸载文件系统 |
不更新atime,适用于频繁读取文件的业务减少磁盘写
1 | [root@student02 ~]# mount -o remount,noatime /home/ |
6. cache
磁盘写入数据,数据先写到硬盘的缓存中,进行io的聚合排序后,再从缓存写到硬盘中,电梯算法
修改磁盘缓存的队列长度,队列长度越长,io得到更多的聚合,但是更消耗内存。
1 | [root@student02 ~]# cat /sys/block/sda/queue/nr_requests |
7. 读策略
读预取的作用:
- 在处理IO请求时,从磁盘按顺序读取IO数据以外更多的数据,预先缓存到cache中,以便下一个顺序读IO请求到达时,可直接在cache中获取,得到更高的性能表现。
- 当读IO很随机是,不当的读预取策略会给存储系统带来额外的资源开销,不到无法保证后续IO再cache中的命中,而且还会带来性能的降低。
四种预取算法:固定预取、可变预取、智能预取和不预取。
- 固定预取:固定大小数据的预取。
- 可变预取:固定IO数量的预取。
- 智能预取:顺序IO的时候就预取,随机IO的时候就不预取,默认预取算法。
- 不预取:不预取数据。
默认读预取大小
1 | [root@student02 ~]# cat /sys/block/sda/queue/read_ahead_kb |
查询读预取扇区数
1 | [root@student02 ~]# blockdev --getra /dev/sda3 |
修改读预取扇区数
1 | [root@student02 ~]# blockdev --setra 4096 /dev/sda3 |
想要重启生效,需要写到开机脚本里面
1 | [root@student02 ~]# echo "blockdev --setra 4096 /dev/sda3" >>/etc/rc.local |
8. scheduler,磁盘调度算法,可以搭配tuned来使用
三种调度算法:
- deadline:最终期限,适合小IO,一个IO读500ms或者写了5000ms没有完成,就放到队列里面排队,优化了等待时间。
- noop:不使用任何参数
- cfq:完全公平,轮询,默认算法
查看当前的调度算法
1 | [root@student02 ~]# cat /sys/block/sda/queue/scheduler |
修改调度算法
1 | [root@student02 ~]# echo deadline > /sys/block/sda/queue/scheduler |
deadline的算法参数front_merges、read_expire、write_expire
1 | [root@student02 ~]# ls /sys/block/sda/queue/iosched/ |
查询内核参数
1 | [root@student02 kernel-doc-3.10.0]# grep -irn --color=auto ^read_expire . |
cfq模式下可以用ionice做进程优先级微调
ionice的级别
- class1,实时的,子级别有0-7,数字越大优先级越低
- class2,尽力的,子级别有0-7,数字越大优先级越低
- class3,空闲的
修改优先级
1 | [root@student02 ~]# pidof vsftpd |
五、Linux模块的调优
1. 列出系统中加载的模块,查找ext4文件系统模块
1 | [root@student02 ~]# lsmod |grep ^ext4 |
Module
:模块名Size
:模块大小Used
:正在使用次数by
:描述
2. 查看模块驱动的详细信息
1 | [root@student02 ~]# modinfo st |
3. 手动加载模块
1 | [root@student02 ~]# modprobe st |
4. 手动卸载模块
1 | [root@student02 ~]# modprobe -r st |
5. 查看模块驱动的参数fixed_buffer_size
1 | [root@student02 st]# modinfo st |grep parm |grep buffer_kbs |
六、内存的调优
1. 当在Linux下频繁存取文件后,cached占用很多资源,虽然cache是为了提高文件读取效率,在有需求的情况下通过命令可以清空缓存
先用free命令查看缓存的使用情况
1 | [root@student02 ~]# free -m |
看到buff/cache占用了768M的内存空间,在清空缓存前用sync命令把dirty页的内容写回硬盘,以免数据丢失
1 | [root@student02 ~]# sync |
现在可以尝试使用内核参数vm.drop_caches来清空缓存
1 | [root@student02 ~]# sysctl -w vm.drop_caches=3 |
再来看看缓存的情况
1 | [root@student02 ~]# free -m |
发现已经只有90M的buff/cache,free的内存空间大了很多
2. 虚拟内存与物理内存
查看进程占用的虚拟内存和物理内存
1 | [root@student02 ~]# ps -aux |grep -E "^nginx|RSS" |grep -v grep |
VSZ
:申请虚拟内存大小,不是立即使用这么多内存RSS
:实际占用物理内存大小
3. PTE和TLB
PTE,页表条目 (Page Table Entry),是页表的最低层,它直接处理页,该值包含某页的虚拟内存到物理内存的映射关系
TLB,是虚拟寻址的缓存,其中每一行都保存着一个由单个PTE(Page Table Entry,页表项)组成的块,用于虚拟地址与实地址之间的交互,提供一个寻找实地址的缓存区,能够有效减少寻找物理地址所消耗时间。
hugepage,大页,用来做TLB的
配置hugepage,添加内核参数,分配40M空间
1 | [root@student02 ~]# sysctl -a |grep -w vm.nr_hugepages |sed 's/0/20/' >>/etc/sysctl.conf |
默认是不启用大页的,大页的空间是立即分配的,不使用也会占用一段内存
4. 页中断
查看进程的次页中断和主页中断
1 | [root@student02 ~]# ps axo comm,pid,min_flt,maj_flt |grep -iE "command|nginx" |
打开一个进程,需要去分配内存叫页中断,可以直接在内存中调用叫次页中断,需要去硬盘swap中调用叫主页中断,出现大量主页中断的时候就说明内存存在瓶颈
5. 内存页的状态
内存页的四种状态:free
:是空闲的页,随时可以被使用inactive clean
:未激活的干净的页,页中的数据已经写到磁盘中,从磁盘读到内存中未被修改,这个页也可以分配,例如,cachedinactive dirty
:脏页,不能被使用,页中的数据修改未写到磁盘,例如脏页,特别是复制文件的时候,dirty是实时变化的active
:激活的页,正在被进程使用,不能被分配
查看脏页的大小
1 | [root@student02 ~]# cat /proc/meminfo |grep -w Dirty |
脏页快速回写的百分比
1 | [root@student02 ~]# sysctl -a|grep dirty_ratio |
当脏页占用内存20%以下的时候,低速写到磁盘中,高于20%的时候高速写回磁盘中,大io可以设置比较小,快点写入硬盘,小io可以慢点写入硬盘,得到聚合,存储一般设置比较高,因为存储有掉电保护BBU
脏页的过期时间
1 | [root@student02 ~]# sysctl -a|grep dirty_exp |
默认30s,30s到了即使比例不达到20%也要快速写到磁盘中
脏页比例的检查时间,5s
1 | [root@student02 ~]# sysctl -a|grep dirty_w |
也可以用命令sync立即把脏页内容写到硬盘
1 | [root@student02 ~]# sync |
还有一个文件也可以强制同步,还支持很多其他指令,模拟各种场景,可以查看内核文档
1 | [root@student02 ~]# echo s >/proc/sysrq-trigger |
当内存紧张的时候倾向于释放cached使用还是去使用swap,值为0到100,0倾向于保留cached使用swap,100倾向于释放cached
1 | [root@student02 ~]# sysctl -a|grep swapp |
6. 内存溢出
oom-kill,内存溢出的保护机制
1 | [root@student02 ~]# echo -17 >/proc/1161/oom_adj |
这个值的取值范围-17到15,值越小,内存溢出不会杀死这个进程,我们可以把重要的进程值设置比较小,不重要的进程设置为15,内存溢出的时候优先杀死这个进程,腾出内存来,重启生效需要写到开机脚本里
关闭oom-kill的功能
1 | [root@student02 ~]# sysctl -a |grep -i panic_on_oom |
这个值设置为1,关闭oom-kill
7. 内存泄漏
进程使用了内存,进程结束也不能回收的部分内存,只有重启才能回收泄漏的内存
检查程序的内存泄漏
1 | [root@student02 ~]# valgrind --tool=memcheck vsftpd |
8. swap
释放swap的空间
1 | [root@student02 ~]# swapoff -a |
新增swap分区
1 | [root@student02 ~]# mkswap /dev/sda4 |
查看swap分区
1 | [root@student02 ~]# swapon -s |
当有几个swap分区时,设置优先级,数字越大优先级越高,优先级一样高,则轮询使用
1 | [root@student02 ~]# cat /etc/fstab |grep swap |
9. 共享内存
系统安装的时候有一个挂载设备/dev/shm,大小是内存的一般,这个设备就是用来做共享内存的,可以把内存当做磁盘使用,有很快的速度,满足一些业务的需求
查看共享内存的大小
1 | [root@student02 ~]# df -h |grep shm |
设置shm分区的大小
1 | [root@student02 ~]# cat /etc/fstab |grep shm |
squid做反向代理就会使用共享内存
10. 内存复用
1 | [root@student02 ~]# sysctl -a |grep overcommit |
0代表更多的尝试过量使用,能过量的就给,1总是过量使用内存,不能过量就释放别的进程,可能把系统搞死机,2能申请的内存等于swap加上内存的百分比,设置模式为0和1的时候百分比设置无效,设置模式2才有效
七、cpu与进程的调优
1. irq的均衡
每个设备都有自己的irq号码,查看设备的中断号
1 | [root@student02 ~]# cat /proc/interrupts |
第一列数字就是设备中断号,我们看到网卡的中断号是18
CPU1对应的数字在增大,CPU1处理网卡的任务
1 | [root@student02 ~]# cat /proc/interrupts |grep -E "CPU|ens32" |
设置网卡的亲和性,让CPU0处理网卡的任务
1 | [root@student02 ~]# echo 1 > /proc/irq/18/smp_affinity |
4U的服务器设置4个CPU同时处理网卡的任务
1 | [root@student02 ~]# echo f > /proc/irq/18/smp_affinity |
同理,可以设置其他设备的CPU亲和性
1 | [root@student02 ~]# echo x > /proc/irq/{irq_number}/smp_affinity |
注:x是一个16进制的数值,f的16进制是1111,代表4个CPU同时工作
2. 均衡CPU的访问次数
任务会在所有CPU上面均衡,繁忙的时候100ms均衡一次,空闲的时候1ms均衡一次,用以下命令可以看到cp文件的时候cpu在不停的均衡
1 | [root@student02 ~]# watch -n .1 'ps axo comm,pid,psr |grep cp' |
CPU的调度均衡可以平衡CPU的负载,但是也会降低缓存的命中率
如果想提高CPU缓存命中率,可以设置进程运行在某个CPU上面
1 | [root@student02 ~]# taskset -p 1 5993 |
3. cpu的隔离
开机内核启动的时候隔离某个cpu,用来运行单独的业务,可以使用taskset命令
1 | [root@student02 ~]# grep isolcpus /boot/grub2/grub.cfg |
4. 在线关闭cpu
当服务器某个cpu故障的时候,我们又不能关机更换CPU,这时候就可以使用以下命令关闭故障cpu在线更换
1 | [root@student02 ~]# echo 0 >/sys/devices/system/cpu/cpu0/online |
lscpu命令可以看到有一个cpu被关闭了
1 | [root@student02 ~]# lscpu |head -n 6 |
5. 调度域,cgroup之cpuset
所谓cpuset,就是在用户空间中操作cgroup文件系统来执行进程与cpu和进程与内存节点之间的绑定,限制进程只能使用子cpuset里面的资源
根cpuset包含所有的资源
1 | [root@student02 ~]# cat /sys/fs/cgroup/cpuset/cpuset.cpus |
创建一个子cpuset,包含1号cpu,和所有内存,因为虚拟机不支持NUMA,所以只能设置所有内存
1 | [root@student02 ~]# mkdir /sys/fs/cgroup/cpuset/mycpuset/ |
还可以设置某个进程运行在cpuset里面,根cpuset包含了所有的进程
1 | [root@student02 ~]# cat /sys/fs/cgroup/cpuset/tasks |
让nginx进程运行在mycpuset里面,同时根cpuset里面没有这个进程了
1 | [root@student02 ~]# pidof nginx |
反过来看进程在哪个cpuset里面
1 | [root@student02 ~]# cat /proc/1697/cpuset |
以上的配置都是重启不会生效的,如果要重启生效需要写到cgroup里面
1 | [root@student02 ~]# cat /etc/cgconfig.conf |grep -A 5 mycpuset |
重启nginx服务测试
1 | [root@student02 ~]# nginx -s stop ;nginx |
默认情况下多个子cpuset可以同时使用cpu的资源,如果想要一个cpuset独占cpu资源,可以打开这个开关,需要开机生效也要写到
1 | [root@student02 ~]# echo 1 >/sys/fs/cgroup/cpuset/cpuset.cpu_exclusive |
6. 进程上下文切换cs
上下文切换的理解
context switch过高会导致CPU像个搬运工,频繁在寄存器和运行队列之间奔波,更多的时间花在了线程切换,而不是真正工作的线程上。直接的消耗包括CPU寄存器需要保存和加载,系统调度器的代码需要执行。间接消耗在于多核cache之间的共享数据。
引起上下文切换的原因
- 当前任务的时间片用完之后,系统CPU正常调度下一个任务;
- 当前任务碰到IO阻塞,调度线程将挂起此任务,继续下一个任务;
- 多个任务抢占锁资源,当前任务没有抢到,被调度器挂起,继续下一个任务;
- 用户代码挂起当前任务,让出CPU时间;
- 硬件中断;
进程上下文切换的检查
1 | [root@student02 ~]# vmstat 1 5 |
bi
:block in数量bo
:block out数量in
:每称的中断数cs
:每秒的上下文切换
每个进程每秒刷新输出上下文切换情况
1 | [root@student02 ~]# pidstat -w 1 5 |
cswch
:自愿的上下文切换nvcswch
:非自愿的上下文切换
看出主机上总的上下文件切换的情况
1 | [root@student02 ~]# sar -w 1 5 |
查看具体进程的每秒上下文切换
1 | [root@student02 ~]# grep ctxt /proc/1501/status |
cswch/s
: 每秒任务主动(自愿的)切换上下文的次数,当某一任务处于阻塞等待时,将主动让出自己的CPU资源。nvcswch/s
: 每秒任务被动(不自愿的)切换上下文的次数,CPU分配给某一任务的时间片已经用完,因此将强迫该进程让出CPU的执行权。
nagios check_mk默认有对上下文的监控,其使用的方法是通过两/proc/stat文件里取到ctxt行,并取两个时间段之间的差值来确认。
1 | [root@student02 ~]# cat /proc/stat|grep ctxt |
7. 运行队列
每个CPU有两个运行队列,活动队列和过期队列,正在运行的任务被优先级高的抢占了,这个任务就到了过期队列,活动队列的任务运行完了,就又变成活动队列继续处理,活动队列和过期队列是一直相互交换的
nice的默认优先级区间为-20到19,数字越小,优先级越高
优先级有两种,静态优先级和动态优先级,nice是动态优先级,他的-20到19对应100-139,对应的静态优先级都是0
修改nice优先级
1 | [root@student02 ~]# renice -20 1805 |
进程有三种优先级,f大于r大于o的优先级
sched_fifo先进先出,一个任务处理完了才轮到下个任务,一个优先级高的任务来了要先处理,处理完了继续我这个任务
sched_rr轮询,每个任务相同的时间,但是优先级高的拥有更多的时间片
sched_other其它优先级,nice,renice
给进程设置先进先出优先级,也可以跟命令
1 | [root@student02 ~]# chrt -f -p 20 1805 |
给进程设置轮询优先级
1 | [root@student02 ~]# chrt -r -p 20 1805 |
八、TCP/IP、Socket参数
所有的TCP/IP参数都位于/proc/sys/net目录下,对/proc/sys/net目录下内容的修改都是临时的,需要写到sysctl.conf文件中
参数(路径+文件) | 描述 | 默认值 | 优化值 |
---|---|---|---|
/proc/sys/net/core/rmem_default | 默认的TCP数据接收窗口大小(字节) | 229376 | |
/proc/sys/net/core/rmem_max | 最大的TCP数据接收窗口(字节) | 131071 | |
/proc/sys/net/core/wmem_default | 默认的TCP数据发送窗口大小(字节) | 229376 | |
/proc/sys/net/core/wmem_max | 最大的TCP数据发送窗口(字节) | 131071 | |
/proc/sys/net/core/netdev_max_backlog | 在每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目 | 1000 | |
/proc/sys/net/core/somaxconn | 定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数 | 128 | |
/proc/sys/net/core/optmem_max | 表示每个套接字所允许的最大缓冲区的大小 | 20480 | |
/proc/sys/net/ipv4/tcp_mem | 确定TCP栈应该如何反映内存使用,每个值的单位都是内存页(通常是4KB)。第一个值是内存使用的下限;第二个值是内存压力模式开始对缓冲区使用应用压力的上限;第三个值是内存使用的上限。在这个层次上可以将报文丢弃,从而减少对内存的使用。对于较大的BDP可以增大这些值(注意,其单位是内存页而不是字节) | 94011 125351 188022 | |
/proc/sys/net/ipv4/tcp_rmem | 为自动调优定义socket使用的内存。第一个值是为socket接收缓冲区分配的最少字节数;第二个值是默认值(该值会被rmem_default覆盖),缓冲区在系统负载不重的情况下可以增长到这个值;第三个值是接收缓冲区空间的最大字节数(该值会被rmem_max覆盖) | 4096 87380 4011232 | |
/proc/sys/net/ipv4/tcp_wmem | 为自动调优定义socket使用的内存。第一个值是为socket发送缓冲区分配的最少字节数;第二个值是默认值(该值会被wmem_default覆盖),缓冲区在系统负载不重的情况下可以增长到这个值;第三个值是发送缓冲区空间的最大字节数(该值会被wmem_max覆盖) | 4096 16384 4011232 | |
/proc/sys/net/ipv4/tcp_keepalive_time | TCP发送keepalive探测消息的间隔时间(秒),用于确认TCP连接是否有效 | 7200 | |
/proc/sys/net/ipv4/tcp_keepalive_intvl | 探测消息未获得响应时,重发该消息的间隔时间(秒) | 75 | |
/proc/sys/net/ipv4/tcp_keepalive_probes | 在认定TCP连接失效之前,最多发送多少个keepalive探测消息 | 9 | |
/proc/sys/net/ipv4/tcp_sack | 启用有选择的应答(1表示启用),通过有选择地应答乱序接收到的报文来提高性能,让发送者只发送丢失的报文段,(对于广域网通信来说)这个选项应该启用,但是会增加对CPU的占用。 | 1 | |
/proc/sys/net/ipv4/tcp_fack | 启用转发应答,可以进行有选择应答(SACK)从而减少拥塞情况的发生,这个选项也应该启用。 | 1 | |
proc/sys/net/ipv4/tcp_timestamps | TCP时间戳(会在TCP包头增加12个字节),以一种比重发超时更精确的方法(参考RFC 1323)来启用对RTT 的计算,为实现更好的性能应该启用这个选项。 | 1 | |
/proc/sys/net/ipv4/tcp_window_scaling | 启用RFC 1323定义的window scaling,要支持超过64KB的TCP窗口,必须启用该值(1表示启用),TCP窗口最大至1GB,TCP连接双方都启用时才生效。 | 1 | |
/proc/sys/net/ipv4/tcp_syncookies | 表示是否打开TCP同步标签(syncookie),内核必须打开了CONFIG_SYN_COOKIES项进行编译,同步标签可以防止一个套接字在有过多试图连接到达时引起过载。 | 1 | |
/proc/sys/net/ipv4/tcp_tw_reuse | 表示是否允许将处于TIME-WAIT状态的socket(TIME-WAIT的端口)用于新的TCP连接 。 | 0 | |
/proc/sys/net/ipv4/tcp_tw_recycle | 能够更快地回收TIME-WAIT套接字。 | 0 | |
/proc/sys/net/ipv4/tcp_fin_timeout | 对于本端断开的socket连接,TCP保持在FIN-WAIT-2状态的时间(秒)。对方可能会断开连接或一直不结束连接或不可预料的进程死亡。 | 60 | |
/proc/sys/net/ipv4/ip_local_port_range | 表示TCP/UDP协议允许使用的本地端口号 | 32768 61000 | |
/proc/sys/net/ipv4/tcp_max_syn_backlog | 对于还未获得对方确认的连接请求,可保存在队列中的最大数目。如果服务器经常出现过载,可以尝试增加这个数字。 | 2048 | |
/proc/sys/net/ipv4/tcp_low_latency | 允许TCP/IP栈适应在高吞吐量情况下低延时的情况,这个选项应该禁用。 | 0 | |
/proc/sys/net/ipv4/tcp_westwood | 启用发送者端的拥塞控制算法,它可以维护对吞吐量的评估,并试图对带宽的整体利用情况进行优化,对于WAN 通信来说应该启用这个选项。 | 0 | |
/proc/sys/net/ipv4/tcp_bic | 为快速长距离网络启用Binary Increase Congestion,这样可以更好地利用以GB速度进行操作的链接,对于WAN通信应该启用这个选项。 | 1 |