美文网首页
系统调优

系统调优

作者: epiiplus1equal0 | 来源:发表于2019-07-23 01:21 被阅读0次

    reference1: 邹sir的rh442系统调优课程

    系统调优

    [TOC]

    reference1: 邹sir的调优课程

    推荐书目: <Linux服务器性能调整>

    基本概念

    <font color=#ff0000>调优是一门黑色艺术</font>

    调优方法(由好到差):

    <font color=#ff0000>架构 -> 硬件 -> 软件配置(SQL调优)</font>

    关闭不需要的服务

    换算单位:

    KB的单位: KiBi的单位 :
    1000 1024
    sosreport # 会在/tmp下生成报告文件
    

    系统内核帮助手册:

    # 软件包: kernel-doc, 安装好之后可在以下目录查询:
    /usr/share/doc/kernel-doc-*/Documentation/
    # 只有redhat7光盘无此包
    grep -irn ip_forwrad 目录 # 可利用此命令查你需要的参数在哪个文件中
    

    如何监控系统

    1. iostat

    yum whatprovides "*/sar"
    yum -y install sysstat
    
    iostat # 展示系统从开机到现在的统计信息(静态, 平均值且非实时), 包括CPU, 磁盘
      %user # 应用程序所占的百分比
      %nice # 调整应用程序的优先级从而使CPU不停切换进程,消耗系统资源所占的百分比
      %system # 内核所占的百分比
      %iowait # IO相关百分比
      %steal # 虚拟化所占百分比
      %idle # 空闲率
    
    iostat.png iostat_tps.png
    tps kB_read/s kB_wrtn/s kB_read kB_wrtn
    22 444 451 5963560 6060483
    每秒传输的io请求数 开机到现在的读

    从上面的表格中提供的数据可以计算出系统每个IO大小的平均值: ( 444 + 451 ) / 22 = 40, 根据此处计算出的结果可以获得系统内的IO是小IO (小于64K)还是大IO (大于64K), 从而进行对应的调优

    # 实例1: 只显示设备的统计信息
    iostat -d 2 6
    
    # 实例2: 显示指定的磁盘sda和sdb
    iostat -x sda sdb 2 6
    
    # 实例3: 显示制定设备的分区的统计信息
    iostat -p sda 2 6
    
    # 实例4:
    iostat -k|-m # 单位
    

    2. iotop

    当系统的%iowait值非常高时, 说明系统IO等待时间非常高, 此时可用iotop查看哪个程序导致io负载高:

    iotop # simple top-like I/O monitor
    
    iotop.png
    dd if=/dev/zero of=/tmp/test.txt bs=1M count=2048 oflag=direct
      # 此命令的if和of本身写于内存
      # oflag=direct 直接写入磁盘
    
    iotop(oflag=direct).png

    3. 衡量硬盘的性能指标

    • IOPS: 每秒处理的IO次数
      • 随机的小IO一般用此参数衡量
      • 用途: 数据库(OLTP, 联机事务处理): 例如银行的每次交易
    • 带宽: 每秒处理的数据大小
      • 顺序的大IO
      • 用途: 1. 备份数据; 2. 视频监控

    下为实例:

    硬盘类型 IOPS/延迟 带宽
    SSD > 2000/1ms 100MB/s
    15K HHD 200/10ms 30MB/s

    4. sar

    Collect, report, or save system activity information

    可查看之前某个时刻和当前时刻的系统信息, 此命令比较全面, 可以实时查看系统的cpu, 内存, 磁盘, swap信息

    alias sar='LANG=C sar' # 设置显示的时间格式为24小时制
    
    sar -u # 查看实时的cpu信息, 与iostat的不同之处在于iostat查看到的是开机到现在的 
    
    sar_u.png
    iostat -q # 查看队列长度和1分钟, 5分钟, 15分钟的平均负载
    
    sar_q.png
    sar -r # 查看内存, 类似free -m
    
    sar_r(free).png
    sar -b 1 5 # 查看硬盘设备的实时io数, 注意和iostat之间的区别, 首先单位就不一样
    
    sar_b.png
    sar -S # 查看swap的信息
    sar -d 1 5 # 显示主次设备编号(利用ll /dev/sd* 可查看对应关系)
    sar -d -p 1 5 # 显示对应设备名的设备
    sar -r -f /var/log/sa/sa08 # /etc/cron.d/sysstat文件里设置系统每隔10分钟, 会将系统状态记录到/var/log/sa/sa${DATE}文件中, 但这些文件需要通过-f选项指定file才能查看, 以及在每天的23:53会执行命令记录系统状态并记录到/var/log/sa/sar${DATE}文件中, 这些文件通过less可以直接查看
    sar -d -p -s 19:00:00 -e 19:40:00 -f /var/log/sa/sa14
      -s [hh:mm:ss] # start time
      -e            # end time
      -A            # 指定显示系统的所有信息
    sar -n DEV 1 5  # 查看network信息, DEV选项表是查看network devices信息
    sar -u 1 5 -o /tmp/sar.data # 将cpu信息收集并存入/tmp/sar.data文件中, 查看时需用-f指定文件
    
    time cp -r /etc/ /tmp # 计时
    watch -n 1 free -m # 每秒监视一次
    vmstat # 查看进程, 内存, swap, io, system, cpu的统计信息
    bigmem 500 # 申请使用500M内存
    
    # top命令解释:
    cp -a /etc/ /tmp/ # 输入命令后使用ctrl + z 暂停
    top # 然后用top命令查看时会发现后台的Tasks中会有一个stopped显示, 就是刚才暂停的任务
    

    5. pmstat

    yum -y install pcp pcp-gui
    # 安装这两个包时可能报错: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2
    # 解决方法: https://blog.51cto.com/dihuo/1568438
    # 在/usr/share/yum-cli/yummain.py和/usr/lib64/python2.7/encodings/utf_8.py中加入三行
    import sys
    reload(sys)
    sys.setdefaultencoding('gbk')
    
    ssh root@ip -X # 让ssh支持图形化界面展示
    

    6. gunplot

    Queue Theory

    <font color=#ff0000>根据下面的公式可以判断系统的瓶颈在哪里!</font>

    调优思想的起源, 利特尔定律: L = A * W

    • L: 队列长度, 系统有多少请求在等待

      • 队列位于内存的buffer中
        • 长: 消耗内存, 但可重新整合IO, 然后写入磁盘, 减少磁盘的寻道次数
        • 短: 优化内存, 但数据写入磁盘时寻道次数多
    • A: 到达率, 每秒来的请求数

    • W: 等待时间, 每个请求需要多长时间处理

    cat /proc/meminfo | grep Dirty # 查看内存中的脏数据
    sysctl -a | grep dirty # 其中有个内核参数: vm.dirty_expire_centisecs = 3000
                           # 用来设定脏数据的过期时长: 3000 (百分之一秒)
                           # 30s后内存中的脏数据写回磁盘, 可临时将此值调大:
    sysctl -w vm.dirty_expire_centisecs=6000
    # 当数据都是随机的小IO时, 让其充分整合以提升性能
    
    # 如果要永久生效:
    vi /etc/sysctl.conf
    vm.dirty_expire_centisecs=6000 # 添加此项
    sysctl -p # 重载配置文件: sysctl.conf和sysctl.d/*.conf
    

    w = Q + S

    • Q: 队列等待时间
    • S: 服务时间

    类比与去银行处理业务: 整个等待时间W = 银行排队时间Q + 银行业务人员处理的时间S

    W = Q + ( T_sys + T_user )

    • T_sys: 内核占用的时间 (打印机, 电脑特别慢)
    • T_user: 应用程序占用的时间 (业务员对业务不熟练)
    # 实例:
    time cp -r /etc/ /data/
    real 0m14.379s
    user 0m0.003s
    sys 0m0.541s
    # T_sys + T_user = 0.544s, 那多的13.835s去哪里了呢? 多的时间其实是Q的时间
    

    内核模块调优

    主要对以下目录进行调优:

    • /proc: 主要是对内核, 文件系统, 进程, 网络调优
    • /sys: 主要是对设备, 驱动, 模块的调优

    <font color=#ff0000>首先强调一点: 所有内核模块都必须匹配内核版本! 内核模块对内核版本非常敏感, 差一个小版本都不行!</font>

    lsmod          # 查看系统当前加载的模块
    modprobe 模块名 # 加载模块
    modprobe -r 模块名 # 卸载模块
    
    modprobe ext4
    # 随便在任意目录下使用modprobe 模块名加载模块, 为什么能够加载成功?
    /lib/modules/$(uname -r)/modules.dep # 加载模块时读会取此文件中记载的模块路径
    
    /boot/initrd-2.6.18-208.el5.img # ram disk, gzip格式压缩的文件, 内含驱动, 安装系统时被读到内存
    zcat initrd-...img | cpio -id # 可将此文件中的内容解压至当前目录
    cpio # 将文件复制到存档包, 也可以从存档包中复制出文件
      -i # 解压
      -d # 目录
    # 解压后的lib/*.ko为各种驱动
    

    <font color=#ff0000>8k: 如何将特定驱动添加到initrd中?</font>

    # 1. 官网下载驱动
    # 2. 编译驱动: /lib/modules/$(uname -r)/kernel/下新建目录, 然后build
    # 3. 备份原有的/boot/initrd-2.6.18-208.el5.img文件
    # 4. mkinitrd --with=lsi2008 --force /boot/initrd-2.6.18-208.el5.img 2.6.18-208.el5
                       # 模块名                                         # 此处不可接绝对路径, 
                                                                       # 且内核版本要与上面编
                                                                       # 译的驱动放置的内核目
                                                                       # 录是同一个才行
    

    模块参数调优 (parm)

    # 系统真实放置模块的位置:
    /lib/modules/$(uname -r)/kernel/drivers/
    
    lsmod ext4
    # 模块名               模块大小  模块使用次数  模块描述
    Module                  Size  Used by
    ext4                  579979  0 
    mbcache                14958  1 ext4
    jbd2                  107478  1 ext4
    
    modinfo ext4 # 查看模块的详细信息
    # 部分模块有一个参数: parm, 可用于调优
    # redhat5有/etc/modprobe.conf, 可直接在此文件内添加内容:
    options snd-card-0 index=0 # 调整模块参数
    # 但redhat6开始需要在/etc/modprobe.d/下新建*.conf文件, 用于调优模块参数:
    vi /etc/modprobe.d/st.conf
    options st buffer_kbs=128 # 特别注意, 模块名和参数不可以写错!
    
    # 修改模块参数后如何验证参数生效?
    # 方法一: 
    # 修改后重载st模块, 然后去/sys/目录下查看参数是否生效
    # 方法二:
    modprobe --showconfig 模块名
    

    <font color=#ff0000>8k: 重建ram disk文件, 解决P2V问题</font>

    • P2V问题: 物理机迁移到虚拟机时系统无法启动
    # redhat5, 6
    mkinitrd /boot/initrd-2.6.18-208.el5xen.img $(uname -r)
    
    # redhat7
    dracut --add-drivers "module1 module2 ..." /boot/initramfs-3.10.0-123.el7.x86_64.img $(uname -r)
      --add-drivers # 可添加模块
    
    # 如何查看redhat7的ram disk文件中的内容:
    /usr/lib/dracut/skipcpio /tmp/initramfs-...img | zcat | cpio -id
    

    小白式系统调优 (redhat7)

    tune: n,v 曲调; 调整

    /usr/lib/tuned/下有可调参数

    yum -y install tuned
    systemctl enable tuned && systemctl start tuned
    tuned-adm list # 列出所有可以调优的参数
    tuned-adm profile throughput-performance # 系统调优, 选用throughput-performance
    tuned-adm list # 马上生效且重启有效
    

    自定义某些配置:

    cd /usr/lib/tuned/
    cp -r throughput-performance/ my442 # 新建自定义目录
    vi my442/tuned.conf # 修改配置你需要的参数
    tuned-adm profile mu442 # 让你配置的参数生效
    

    系统资源限制调优

    # 编辑完limit.conf文件, 立即生效
    rss - max resident set size (KB) # 常驻内存(物理), 无法限制
    as - address space limit (KB) # 虚拟内存, 可做限制
    # 用户可自己调整限制至最大值: ulimit -n 20
    

    Cgroup <==> Controller group

    mount | grep cgroup
    tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,seclabel,mode=755)
    

    软件包: libcgroup (redhat6默认不装, redhat7安装)

    redhat6中如何利用cgroup对系统资源做限制:
    yum -y install libcgroup
    /etc/init.d/cgconfig start # 服务启动后系统就有/cgroup/这个目录
    
    • 临时生效:
    # /cgroup/内控制资源, 可在其内新建目录, 将需要控制的进程对应的PID写入新建目录内的tasks文件中
    mkdir /cgroup/memory/{bigdata,rh442} # 想对bigdata, rh442的内存做限制, 
                                         # 就在/cgroup/memory/目录下新建目录
    echo 102400000 > /cgroup/memroy/rh442/memory.limit_in_bytes # 可通过此方式临时对rh442组的
                                                                # 内存做限制, 只能用100M内存
    echo $(pidof vsftpd) > /cgroup/memory/rh442/tasks # 将需对内存做限制的进程的PID写入rh442组
                                                      # 的tasks中, 这样就对对应进程做了限制
    pmap PID # 查看进程使用内存情况, 可以看到一个进程运行时一共需要的内存
    # 如何删除内存中的文件夹:
    rmdir rh442
    
    • 永久生效: <font color=#ff0000>可对云, 虚拟机, docker等容器使用的资源做限制</font>
    vi /etc/cgconfig.conf # 添加如下内容:
    group bigdata {       # bigdata为需要限制的组的组名, 名字可自定义, 可以创建多个group
        blkio {           # blkio为需要限制的内容
            参数 = "值";   # 可以限制的参数能在/cgroup/blkcio/目录下找到
        }
        memory {
            参数 = "值";
            memory.limit_in_bytes = "100M";
        }
    }
    
    /etc/init.d/cgconfig restart
    # 注: 如果这样配置后在/cgroup/memory/内执行重启命令, 会报错: Device or resource busy
    # 故需要到其他无关目录内重启, 才会成功
    # 这样配置以后重启cgconfig服务, 会在/cgroup/memory/目录下创建文件夹bigdata和memroy, 
    # 但还没针对服务做限制, 因此还需进行下面步骤
    
    vi /etc/cgrules.conf # 策略文件, 添加上述参数对应的配置:
    #用户:命令 需要限制的内容    组名
    *:cp      blkio,memory   bigdata/redhat/ # group内有子组时, 可在bigdata后面添加redhat
    # 上面这行的含义为对所有用户执行cp命令时, 会使用bigdata内关于memory和blkio做限制的参数
    # 在/etc/cgconfig.conf对内存做了100M的限制, 因此超出100M时不会执行cp命令
    *:bigmem              memory  bigdata/ # 命令最好是绝对路径
    *:/etc/init.d/vsftpd  memory  bigdata/ # 针对服务做限制
    
    /etc/init.d/cgred restart
    
    # 也可用以下命令重启服务:
    service cgconfig restart
    service cgred restart
    
    redhat7中如何利用cgroup对系统资源做限制:

    书本P98, P99

    • redhat7内可针对服务或用户做限制

    软件包: memload (类似于bigmem), 可用作测试内存

    memload 256: 单位M, 申请使用256M内存

    man system.resource-control # 查看可以用来限制的参数
    /etc/systemd/system/ # 此目录下针对服务做限制
    /etc/systemd/user/    # 此目录下针对用户做限制
    
    # 实例: 需限制nginx.service的内存使用量为512M
    cd /etc/systemd/system/
    mkdir nginx.service.d # 新建需要限制的服务对应的目录
    vi 00-limit.conf # 新建00-limit.conf文件, 添加以下内容:
    [service]
    MemoryLimit=512M
    
    systemctl daemon-reload # 然后重载以及重启服务, 限制即可生效
    systemctl restart nginx
    

    硬件监控

    CPU

    基本概念:

    • 一个核就是一个cpu
    • 核与线程:
      • 单线程: 人脑处理任务
      • 多线程: 电脑处理2个任务
    • 队列: 10个任务同时来

    衡量cpu性能:

    • lscpu | grep BogoMIPS:

      • BogoMIPS: 5616.00

      • 每秒处理百万指令集的数目, 5616 * 1000,000

    • lscpu | grep "L3 cache"

      • L3 cache: 6144K

    cpu <-- FSB --> mem: cpu和内存之间通过 FSB (前端总线) 交换数据

    • UMA: 一致性内存访问

    • NUMA: 非一致性内存访问, cpu和mem在同一个NUMA node中

      • 优: 减少前端总线的压力
      • 缺: 开启NUMA无法内存复用
    lscpu.jpg
    • L1: 一级缓存, 一般CPU的L1i和L1d具备相同的容量
      • L1d: 数据缓存 (Data Cache, D-Cache)
      • L1i: 指令缓存 (Instruction Cache, I-Cache)
    • L2: 二级缓存
    • L3: 三级缓存

    为什么CPU缓存会分为一级缓存L1、L2、L3?有什么意义?

    • Virtualization type: full (支持全虚拟化)
    # 更加详细的关于cpu的信息, 可以查看:
    cat /proc/cpuinfo
    
    flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec arat spec_ctrl intel_stibp flush_l1d arch_capabilities
    # flags: 支持的指令集, 如lm (long mode, 64bits), vmx (全虚拟化)
    
    address sizes   : 43 bits physical, 42 bits virtual
    # 支持 2^42 = 4TB 的物理内存以及 2^42 = 4TB 的虚拟内存
    

    内存

    dmidecode # 查看内存信息, 如条数, 大小, 插槽, 频宽, 电压, 是否支持NUMA等
    
    numactl # 设置cpu和内存在哪个NUMA node中
    

    存储

    SATA SAS SSD
    容量 > >
    性能 < <

    常用RAID Level:

    1 5 10
    装系统 分布式
    • RAID5:

      • 带奇偶校验的条带化, 有写惩罚
        
        • 大写: > 一半, 读整个分条, 写回 P
        • 小写: < 一半
      • 适用场景: 顺序的大IO ( 如视频监控, 备份, OLAP )
    • RAID10:

      • 使用场景: 随机的小IO ( 如数据库OLTP, 事务型, 交易系统 )
    • FC - SAN: 一般用于公司内部业务, 距离有限

    • IP - SAN: 热备

    网络

    1. 网卡选型
    2. 组网 ( GE/10GE/IB ) 40Gb/56Gb/100Gb
    3. 双网卡绑定模式 ( mode = 0-6 ) 0: 轮循 1: 主备 4: LACP 6: 最佳, 计算最小负载, 然后分发数据包至最小负载那里
    4. VLAN
    5. 网卡是否支持虚拟化: 指令集: VT-d(直通模式, 运算在网卡中进行), VT-x, SR-IOV(单根IO虚拟化, 硬直通, 直通虚拟机网卡)
    cat /var/log/dmesg # 记录启动时的硬件信息
    
    dmesg | grep eth # 可用于判断内核是否识别网卡
    [    2.698411] e1000 0000:02:01.0 eth0: (PCI:66MHz:32-bit) 00:0c:29:8d:4d:36 # mac地址
    [    2.698423] e1000 0000:02:01.0 eth0: Intel(R) PRO/1000 Network Connection # 别名
         # 耗费时间
    dmesg | grep sd # 查看硬盘信息
    [    3.126098] sd 2:0:0:0: [sda] 419430400 512-byte logical blocks: (214 GB/200 GiB)
    [    3.126170] sd 2:0:0:0: [sda] Write Protect is off
    

    <font color=#ff0000>系统启动时, 红字之后的是服务和文件系统的信息 !!!</font>

    生产环境中可能遇到的问题以及一些补充说明

    书本P115:

    系统启动时显示: [<fffff...f 8014ebaf>]kobject_add+0x170/0x196

    <font color=#ff0000>一般是物理机的内存不兼容或者硬件问题造成的.</font>

    lscpu, lspci, lsusb

    # getconf此命令一般用于将系统配置变量值写入标准输出, 本身是个ELF可执行文件,也可以用于获取系统信息
    getconf -a | grep -i page # 查看系统内存分页大小
                              # 内存页: 内存最小单元 (类比与block块的大小), 本例为4K
    PAGESIZE                           4096
    PAGE_SIZE                          4096
      -a # 获取全部系统信息
    
    dmidecode --from-dump 文件名 > dmi.txt # 分析二进制文件
                                          # 可分析出L1, L2的大小, 注意内核个数!
    

    影响磁盘IO性能的因素

    • 机械硬盘:
      • 转数
      • 寻道时间

    存储密度

    <font color=#ff0000>分区号越低, 越靠近外环</font>

    读性能提升

    读预取 (顺序读):

    • 固定预取
    • 倍数预取
    • 智能预取
      • /sys/block/sda/queue/read_ahead_kb --> 4096 KB, 可调整此参数提升读预取的大小
    • 不预取

    写性能提升

    硬盘调优的角度(可针对某块硬盘):

    • 方法一: /sys/block/sda/queue/nr_requests 队列长度
    • 方法二: /sys/block/sda/queue/scheduler 调度算法
      • noop [deadline] cfq, 中括号中为当前使用的调度算法
      • 调整: echo noop > /sys/block/sda/queue/scheduler

    调度算法:

    • deadline 最终期限

      • <font color=#ff0000>适合小IO和ext4文件系统</font>
    • noop 没有任何调优

      • <font color=#ff0000>存储映射时无需调优</font>
    • as 猜想时间

      • <font color=#ff0000>适合大IO和xfs文件系统</font>
    • cfg 给每个应用不同大小

      iostat # 对一个程序设置或获取I/O调度级别和优先级
      ionice -p 1 # 查看PID为1的进程的I/O调度级别以及优先级
      ionice -p 1 -c 1 -n 2 # 设置PID为1的进程为class1, nice值为2
      
    • -c参数:

    class 1 2 3
    优先级 > >
    实时: 先进先出 轮循: n越小, 分到的时间片越多, 但每个进程都会轮到 空闲
    • -n参数:
      • 0 - 7, 越小越重要, 优先级越高

    mailload.py 压力测试工具

    <font color=#ff0000>当然也可以通过tuned.conf修改参数进行调优</font>

    进程管理和调度

    ps axo %cpu,%mem,nice,psr
      nice # 查看进程的优先级
      psr # 显示程序与运行在哪个cpu上
    

    优先级:

    • 静态: 1 - 99, 数字越大, 优先级越高
    • 动态: 0 <=> 100 - 129 ( -20 - 19 )
    chrt -p 1 # 实时查看PID为1的进程优先级
    pid 1's current scheduling policy: SCHED_OTHER
    pid 1's current scheduling priority: 0
    

    <font color=#ff0000>FIFO和RR谨慎使用, 因为一旦使用会将整个CPU占用 !!!</font>

    • SCHED_FIFO

      • 先进先出, first input first output, 优先级 1 - 99
      • 优先级高的会抢占cpu
      • chrt -f 10 dd if=/dev/zero of=/dev/null:实时设置FIFO且优先级为10
    • SCHED_RR

      • 类似FIFO但有时间片的概念
      • chrt -r 20 dd if=/dev/zero of=/dev/null
      • 只有RR级别才会轮循, 优先级越高, 分到的时间片越多
    • SHCED_OTHER

      • nice

      • renice

      • other如何获得更长的时间片?

        • 方法一: 类似cgroup中的内存管理去设置 CPUShares=128 (份额 = 2的倍数), 永久生效

        • 方法二: systemctl set-property httpd.service CPUShares=512, 临时生效

    # 如何对已运行的程序调整优先级:
    chrt -p 2420
    chrt -p -f 10 2420 # 对PID为2420的进程调整优先级为FIFO, 10
    

    跟踪系统和库调用

    系统调用

    <font color=#ff0000>排错时会用到 !</font>

    strace -c ls -l # 计数每步的操作时间
        -c # count
    strace -e read cp -r /etc/ /data/ # 查看read的具体操作
    strace -p PID # 实时查看某程序的系统和库的调用情况
    

    库调用

    ltrace cp # 查看某个命令会调用哪些库
    

    减少磁盘访问次数

    • VFS: 虚拟文件系统, 对应用而言, 只要调用驱动, 写入数据就好了, 所以任何的文件系统对应用来讲都是VFS
    tune2fs -l /dev/vda1 # 查看原数据, 简略
    dumpe2fs /dev/vda1   #           详细
    # 可以看到元数据中由block group, 即分组的概念, 以此保证数据连续
    

    <font color=#ff0000>8K: 超级块损坏时如何修复? 一定要记得先卸载分区再修复 !!!</font>

    dd if=/dev/zero of=/dev/vda1 bs=1k count=20 # 模拟生产环境中超级块损坏的情况, 此处为破坏超级块
    
    # 修复ext类型文件系统:
    # 方法一:
    umount /dev/vda1
    fsck -v /dev/vda1 # 一直yes
    # 方法二:
    umount /dev/vda1
    e2fsck -b 98304 /dev/vda1 # 使用98304的超级块来恢复, 
                              # 特别注意, 不同的文件系统, 超级块的位置固定的
    
    # 修复xfs类型文件系统:
    xfs_repair /dev/vda1
    

    日志型文件系统

    ext3/ext4/xfs/NTFS

    • 优: 减少开机扫描

    • 缺: 写数增加( 两次写: 1. journal 2.inode )

    外部日志区如何配置

    条件:

    • (1) journal size =2^N < 400M
    • (2) 整个分区只能用于journal device, 不能用作其他
      • <font color=#ff0000>多个文件系统可以共用一个外部日志区, 不过block size必须相同</font>
    • (3) journal block size 必须与源文件系统一致

    现在有两块硬盘, sda1和sdb1, 需要将sdb1用作sda1的外部日志区, 从而减少硬盘访问次数, 下面为配置方法:

    # 1. 卸载文件系统
    umount /dev/sda1
    umount /dev/sdb1
    
    # 2. 查看文件系统的block大小及日志位置
    dumpe2fs /dev/sda1 | egrep -i (journal|size)
    
    # 3. 在已存在的文件系统中删除内部日志
    tune2fs -O ^has_journal /dev/sdb1
    
    # 4. 创建一个扩展的日志设备
    mke2fs -O journal_dev -b block_size /dev/sdb1
    
    # 5. 更新文件系统的超级块, 从而使用扩展的日志
    tune2fs -j -J device=/dev/sdb1 /dev/sda1
    

    cpu的IRQ均衡 (IRQ balance)

    <font color=#ff0000>用来均衡cpu的访问次数, 但cpu的缓存效果会减弱</font>

    • 每个硬件都会对应一个中断号, 一般IRQ只会指向某一个cpu, 所以某个设备只会在使用对应的cpu跑任务, 即只在某个cpu上消耗资源
    cat /proc/interrupts
    
    interrupts.png
    中断号 CPU0 CPU1 CPU2 CPU3
    19: 8417 0 0 0 IO-APIC-fasteoi eno16777736
    cpu编号说明: 2^0=1 2^1=2 2^2=4 2^3=8
    cat /proc/irq/19/smp_affinity # smp_affinity: 多处理器亲缘
    08                            # 说明只用了CPU3
    cat /proc/irp/27/smp_affinity
    20                            # 2^2 + 2^4 = 20, 使用了CPU2和CPU4
    

    修改多处理器亲缘:

    echo 2 > /proc/irq/19/smp_affinity # 将多处理器亲缘改为CPU1
    echo 3 > /proc/irq/3/smp_affinity  # 改为使用CPU0和CPU1, f: 15
    

    Tuning process affinity with taskset (不均衡)

    • 一般应用程序运行的时候会在不同的cpu上来回切换: ps axo %cpu,%mem,psr
    • 优: 设置应用程序运行在指定的某个cpu或某些cpu上, 提高缓存命中率, 从而提升性能
    • 缺: 不均衡的运行队列会导致较长的等待时间, 一般用于NUMA架构
    taskset -p PID # 查看PID的进程运行在哪个cpu上
    taskset -p 3 PID # 此处的3为16进制, 例如1, 2, 4, 8, f
    

    cpu隔离

    如何做cpu隔离, 实现某个cpu只运行特定程序?

    # 1. 启动时编辑/etc/grub.conf, 隔离cpu
    isolcpus=cpu_number,cpu_number,... # 设定只使用某几个cpu, 其他不用
    
    # 2. 设定某个程序运行在特定cpu上
    taskset -p cpu_number PID
    
    # 3. 考虑调整IRQ亲缘
    

    cpu支持热插拔

    • CPU0以外的cpu支持如拔插, 0号不支持的原因是因为它是启动cpu
    • 支持热拔插的前提: 硬件支持 (BIOS支持物理热拔插)
    • 对NUMA系统非常有用
    • 热拔插的操作后内核会动态更新/proc/cpuinfo及其他文件内的信息
    • see kernel-doc-*/Documentation/cpu-hotplug.txt
    # 1. 查看cpu号
    grep processor /proc/cpuinfo
    cat /proc/interrupts
    
    # 2.动态关闭某个cpu, 如cpu1
    echo 0 > /sys/devices/system/cpu/cpu1/online # online: 相当于一个开关
    cat /proc/interrupts # 关闭后无法看到cpu1的信息
    
    # 3. 重开cpu1
    echo 1 > sys/devices/system/cpu/cpu1/online
    cat /proc/interrupts # 再次可以看到cpu1的信息
    

    注: cpu1在被关闭时已有程序在上面运行, 关闭时其上的程序会被迁移到其他cpu, 不会影响原来程序的运行, 就算指定某程序在cpu1上运行, 当cpu1被关闭时, 该程序依旧不会受到影响, 同样会被迁移到其他cpu上, 但cpu1再次被开启时, 原来指定的程序不会再次回到cpu1上运行

    调度域 (scheduler domains)

    • cpuset: 进程组, 支持多核和NUMA架构

    • /sys/fs/cgroup/cpuset/

    cat /proc/filesystem | grep cpuset # 可以看到有种特殊的vfs: cpuset
    nodev cpuset
    
    mkdir /cpuset
    mount -t cpuset nodev /cpuset/
    cd /cpuset/; ls
    cat cpuset.cpus
    0-3       # 包含的cpu号
    cat cpuset.mems
    0         # 包含的内存zone
    cat tasks # 包含的所有任务
    

    此架构用于NUMA特别方便:

    mkdir {rh442,cl210}
    echo 0-1 > rh442/cpuset.cpus # 每个cpuset至少包含一个cpu和一个内存zone
    echo 0 > rh442/cpuset.mems
    echo 2-3 > cl210/cpuset.cpus # cpuset支持嵌套, 故可将 2-3 改为 0-1
    echo 0 > cl210/cpuset.mems
    
    # 关闭cpu嵌套, 注意需要先关闭根cpuset的嵌套才有效
    echo 1 > /cpuset/cpuset.cpu_exclusive
    

    可将指定程序运行在NUMA node中:

    systemctl start vsftpd
    echo $(pidof vsftpd) > /cpuset/rh442/tasks
    

    查看某程序运行在哪个cpuset中, 以vsftpd为例:

    cd /proc/$(pidof vsftpd)
    cat cpuset # 查看到结果为/rh442
    cd /proc/1
    cat cpuset # 查看到结果为/, 根cpuset包含所有系统资源
    

    内存管理(地址和分配)

    • 虚拟内存
      • 应用程序申请的内存 (按需分配)
      • 应用程序申请虚拟内存时时, 总认为<font color=#ff0000>每一个程序都有一段线性的, 连续的地址空间, 但实际映射到的物理内存上是不连续的</font>
      • 地址范围从0到最大值
      • 32bits架构的系统, 内存最大支持 2^32 = 4GB
      • 64bits架构的系统, 内存最大支持 2^48 = 256TB, 但由于内核与硬件的限制, 实际只支持到 2^42 = 4TB
      • 用内存页来表示
    • 物理内存
      • 物理内存 = 内存 + swap, 即 96G = 64G + 32G
        • swap上的数据只做暂存, 不作处理
      • cpu的内存管理单元 MMU: 负责管理虚拟内存与物理内存之间的映射关系
    ps aux | less # 可以查看到虚拟内存VSZ和物理内存RSS的使用情况
    USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root          1  0.0  0.0 193580  6584 ?        Ss    2018  17:55 /usr/lib/systemd/systemd --system --deserialize 20
    root          2  0.0  0.0      0     0 ?        S     2018   0:09 [kthreadd]
    root          3  0.0  0.0      0     0 ?        S     2018   0:25 [ksoftirqd/0]
    root      73900  0.0  0.0 918368 32492 ?        Ssl  May24   0:30 PM2 v3.0.0: God Daemon (/root/.pm2)
    root      86904  0.0  0.0 157860  2424 ?        S    Apr23   0:00 top
    
    bigmem -v 500 # 申请使用500MB虚拟内存
    watch -n 1 'cat /proc/meminfo | grep AS' # AS:地址空间
    
    • PTE: 页表条目 (page table entries)
      • 记录虚拟内存到物理内存的映射关系
    • TLB: 记录PTE内映射关系的缓存
      • Hugepage (大页): 用于存放TLB的缓存数据
        • cat /proc/meminfo | grep -i huge
        • bigmem -H NUM: -H, 指定使用Hugepage, 此命令可用作测试大页
        • 一旦分配了大页, 其他应用程序无法申请到大页使用的内存

    内存架构

    x86, 即32bits的系统上:

    1024M, 具体分配如下 物理内存的第一个GB分配给内核使用 (直接映射内存)
    128M 高位内存, 用于存放PTE
    896M, 包括下面的1M和16M和879M
    1M 给BIOS和IO设备使用
    16M 给DMA (直接内存访问) 使用
    879M 低位内存

    x86_64, 及64bits的系统上:

    128T 系统使用
    128T 应用使用

    页中断 (page fault)

    ps axo pid,comm,minflt,majflt
    PID   COMMAND         MINFLT MAJFLT
    53399 sshd              6937      0
    53401 sftp-server       1444      0
    66588 snmpmagt           637      0
    66872 PatrolAgent     1739153756  0
    66987 pukremotexec.xp    273      0
    73900 PM2 v3.0.0: God 107465      0
    
    • 次页中断
      • 由物理内存分配
    • 主页中断
      • 由swap分配
      • 主页中断越多, 系统性能越差

    页:

    (1) dirty page: 内存中已被修改, 还未写入磁盘的数据, 可用sync命令将drity page的数据写入磁盘

    (2) clean page: free -m中的caches, 以写入磁盘, 但是作为缓存, 提升读性能的数据

    生产环境中一个特别有用的参数: <font color=#ff0000>vm.swappiness</font>

    vm.swappiness默认值的范围在: 0 - 100

    • 此值越高, 越多的使用swap
    • 此值越低, 越多的使用内存
    sysctl -a | grep swappiness
    vm.swappiness = 30
    

    生产环境中, 若swap使用过多, 如何更多的使用内存, 减少swap的使用量:

    # 方法一: 临时生效
    sysctl -w vm.swappiness=20
    # 方法二: 永久生效
    vi /etc/sysctl.conf
    vm.swappiness = 20
    
    sysctl -p
    

    如果需要清空swap中的缓存, 该怎么做?

    # 先看看当前swap和内存的使用情况: 如果swap使用量已经超过内存的空闲量, 则无法被清空!
    swapon -s
    Filename                                Type            Size    Used    Priority
    /dev/sda1                               partition       8257532 8257532 -1
    
    swapoff /dev/sda1 # 一定要注意, 生产环境中千万不要随便去卸载swap!!!
    watch -n 1 'free -m'
    

    扩展swap

    一些概念:

    • 冷数据, anon (匿名页, 可用命令pmap查看) 都会大量放于swap中.

    • 一般内存越大, swap也分配的越大, 因为内存中的冷数据也越多.

    如何提升swap的性能:

    • 将swap分到不同的硬盘上
    • 分配分区号小的分区, (分区号越小, 越靠近外圈, 磁头每转过一圈读取到的数据越多)

    方法一: 使用硬盘分区

    <font color=#ff0000>注: swap分区Priority的值越大, 优先级越高, 越先被使用!</font>

    # (1) 先在不同的两块硬盘上都分出1个分区, 都用作swap
    fdisk /dev/sdb # 分出/dev/sdb1
    fdisk /dev/sdc # 分出/dev/sdc1
    
    # (2) 然后格式化
    mkswap /dev/sdb1
    mkswap /dev/sdc1
    
    # (3) 编辑/etc/fstab, 注意调整各自的优先级, 做到均衡使用两个分区的swap (即轮循)
    vi /etc/fstab # UUID可用命令blkid查看
    UUID="..." swap swap defaults,pri=-2 0 0
    UUID="..." swap swap defaults,pri=-2 0 0
    

    方法二: 使用文件

    RHCE课程中已学过, 此处不再赘述.

    相关文章

      网友评论

          本文标题:系统调优

          本文链接:https://www.haomeiwen.com/subject/izknlctx.html