reference1: 鄒sir的rh442系統(tǒng)調(diào)優(yōu)課程
系統(tǒng)調(diào)優(yōu)
[TOC]
reference1: 鄒sir的調(diào)優(yōu)課程
推薦書目: <Linux服務(wù)器性能調(diào)整>
基本概念
<font color=#ff0000>調(diào)優(yōu)是一門黑色藝術(shù)</font>
調(diào)優(yōu)方法(由好到差):
<font color=#ff0000>架構(gòu) -> 硬件 -> 軟件配置(SQL調(diào)優(yōu))</font>
關(guān)閉不需要的服務(wù)
換算單位:
KB的單位: | KiBi的單位 : |
---|---|
1000 | 1024 |
sosreport # 會在/tmp下生成報告文件
系統(tǒng)內(nèi)核幫助手冊:
# 軟件包: kernel-doc, 安裝好之后可在以下目錄查詢:
/usr/share/doc/kernel-doc-*/Documentation/
# 只有redhat7光盤無此包
grep -irn ip_forwrad 目錄 # 可利用此命令查你需要的參數(shù)在哪個文件中
如何監(jiān)控系統(tǒng)
1. iostat
yum whatprovides "*/sar"
yum -y install sysstat
iostat # 展示系統(tǒng)從開機到現(xiàn)在的統(tǒng)計信息(靜態(tài), 平均值且非實時), 包括CPU, 磁盤
%user # 應(yīng)用程序所占的百分比
%nice # 調(diào)整應(yīng)用程序的優(yōu)先級從而使CPU不停切換進程,消耗系統(tǒng)資源所占的百分比
%system # 內(nèi)核所占的百分比
%iowait # IO相關(guān)百分比
%steal # 虛擬化所占百分比
%idle # 空閑率
tps | kB_read/s | kB_wrtn/s | kB_read | kB_wrtn |
---|---|---|---|---|
22 | 444 | 451 | 5963560 | 6060483 |
每秒傳輸?shù)膇o請求數(shù) | 開機到現(xiàn)在的讀 |
從上面的表格中提供的數(shù)據(jù)可以計算出系統(tǒng)每個IO大小的平均值: ( 444 + 451 ) / 22 = 40
, 根據(jù)此處計算出的結(jié)果可以獲得系統(tǒng)內(nèi)的IO是小IO (小于64K)還是大IO (大于64K), 從而進行對應(yīng)的調(diào)優(yōu)
# 實例1: 只顯示設(shè)備的統(tǒng)計信息
iostat -d 2 6
# 實例2: 顯示指定的磁盤sda和sdb
iostat -x sda sdb 2 6
# 實例3: 顯示制定設(shè)備的分區(qū)的統(tǒng)計信息
iostat -p sda 2 6
# 實例4:
iostat -k|-m # 單位
2. iotop
當(dāng)系統(tǒng)的%iowait值非常高時, 說明系統(tǒng)IO等待時間非常高, 此時可用iotop查看哪個程序?qū)е耰o負(fù)載高:
iotop # simple top-like I/O monitor
dd if=/dev/zero of=/tmp/test.txt bs=1M count=2048 oflag=direct
# 此命令的if和of本身寫于內(nèi)存
# oflag=direct 直接寫入磁盤
3. 衡量硬盤的性能指標(biāo)
- IOPS: 每秒處理的IO次數(shù)
- 隨機的小IO一般用此參數(shù)衡量
- 用途: 數(shù)據(jù)庫(OLTP, 聯(lián)機事務(wù)處理): 例如銀行的每次交易
- 帶寬: 每秒處理的數(shù)據(jù)大小
- 順序的大IO
- 用途: 1. 備份數(shù)據(jù); 2. 視頻監(jiān)控
下為實例:
硬盤類型 | IOPS/延遲 | 帶寬 |
---|---|---|
SSD | > 2000/1ms | 100MB/s |
15K HHD | 200/10ms | 30MB/s |
4. sar
Collect, report, or save system activity information
可查看之前某個時刻和當(dāng)前時刻的系統(tǒng)信息, 此命令比較全面, 可以實時查看系統(tǒng)的cpu, 內(nèi)存, 磁盤, swap信息
alias sar='LANG=C sar' # 設(shè)置顯示的時間格式為24小時制
sar -u # 查看實時的cpu信息, 與iostat的不同之處在于iostat查看到的是開機到現(xiàn)在的
iostat -q # 查看隊列長度和1分鐘, 5分鐘, 15分鐘的平均負(fù)載
sar -r # 查看內(nèi)存, 類似free -m
sar -b 1 5 # 查看硬盤設(shè)備的實時io數(shù), 注意和iostat之間的區(qū)別, 首先單位就不一樣
sar -S # 查看swap的信息
sar -d 1 5 # 顯示主次設(shè)備編號(利用ll /dev/sd* 可查看對應(yīng)關(guān)系)
sar -d -p 1 5 # 顯示對應(yīng)設(shè)備名的設(shè)備
sar -r -f /var/log/sa/sa08 # /etc/cron.d/sysstat文件里設(shè)置系統(tǒng)每隔10分鐘, 會將系統(tǒng)狀態(tài)記錄到/var/log/sa/sa${DATE}文件中, 但這些文件需要通過-f選項指定file才能查看, 以及在每天的23:53會執(zhí)行命令記錄系統(tǒng)狀態(tài)并記錄到/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 # 指定顯示系統(tǒng)的所有信息
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 # 每秒監(jiān)視一次
vmstat # 查看進程, 內(nèi)存, swap, io, system, cpu的統(tǒng)計信息
bigmem 500 # 申請使用500M內(nèi)存
# top命令解釋:
cp -a /etc/ /tmp/ # 輸入命令后使用ctrl + z 暫停
top # 然后用top命令查看時會發(fā)現(xiàn)后臺的Tasks中會有一個stopped顯示, 就是剛才暫停的任務(wù)
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>根據(jù)下面的公式可以判斷系統(tǒng)的瓶頸在哪里!</font>
調(diào)優(yōu)思想的起源, 利特爾定律: L = A * W
-
L: 隊列長度, 系統(tǒng)有多少請求在等待
- 隊列位于內(nèi)存的buffer中
- 長: 消耗內(nèi)存, 但可重新整合IO, 然后寫入磁盤, 減少磁盤的尋道次數(shù)
- 短: 優(yōu)化內(nèi)存, 但數(shù)據(jù)寫入磁盤時尋道次數(shù)多
- 隊列位于內(nèi)存的buffer中
A: 到達率, 每秒來的請求數(shù)
W: 等待時間, 每個請求需要多長時間處理
cat /proc/meminfo | grep Dirty # 查看內(nèi)存中的臟數(shù)據(jù)
sysctl -a | grep dirty # 其中有個內(nèi)核參數(shù): vm.dirty_expire_centisecs = 3000
# 用來設(shè)定臟數(shù)據(jù)的過期時長: 3000 (百分之一秒)
# 30s后內(nèi)存中的臟數(shù)據(jù)寫回磁盤, 可臨時將此值調(diào)大:
sysctl -w vm.dirty_expire_centisecs=6000
# 當(dāng)數(shù)據(jù)都是隨機的小IO時, 讓其充分整合以提升性能
# 如果要永久生效:
vi /etc/sysctl.conf
vm.dirty_expire_centisecs=6000 # 添加此項
sysctl -p # 重載配置文件: sysctl.conf和sysctl.d/*.conf
w = Q + S
- Q: 隊列等待時間
- S: 服務(wù)時間
類比與去銀行處理業(yè)務(wù): 整個等待時間W = 銀行排隊時間Q + 銀行業(yè)務(wù)人員處理的時間S
W = Q + ( T_sys + T_user )
- T_sys: 內(nèi)核占用的時間 (打印機, 電腦特別慢)
- T_user: 應(yīng)用程序占用的時間 (業(yè)務(wù)員對業(yè)務(wù)不熟練)
# 實例:
time cp -r /etc/ /data/
real 0m14.379s
user 0m0.003s
sys 0m0.541s
# T_sys + T_user = 0.544s, 那多的13.835s去哪里了呢? 多的時間其實是Q的時間
內(nèi)核模塊調(diào)優(yōu)
主要對以下目錄進行調(diào)優(yōu):
- /proc: 主要是對內(nèi)核, 文件系統(tǒng), 進程, 網(wǎng)絡(luò)調(diào)優(yōu)
- /sys: 主要是對設(shè)備, 驅(qū)動, 模塊的調(diào)優(yōu)
<font color=#ff0000>首先強調(diào)一點: 所有內(nèi)核模塊都必須匹配內(nèi)核版本! 內(nèi)核模塊對內(nèi)核版本非常敏感, 差一個小版本都不行!</font>
lsmod # 查看系統(tǒng)當(dāng)前加載的模塊
modprobe 模塊名 # 加載模塊
modprobe -r 模塊名 # 卸載模塊
modprobe ext4
# 隨便在任意目錄下使用modprobe 模塊名加載模塊, 為什么能夠加載成功?
/lib/modules/$(uname -r)/modules.dep # 加載模塊時讀會取此文件中記載的模塊路徑
/boot/initrd-2.6.18-208.el5.img # ram disk, gzip格式壓縮的文件, 內(nèi)含驅(qū)動, 安裝系統(tǒng)時被讀到內(nèi)存
zcat initrd-...img | cpio -id # 可將此文件中的內(nèi)容解壓至當(dāng)前目錄
cpio # 將文件復(fù)制到存檔包, 也可以從存檔包中復(fù)制出文件
-i # 解壓
-d # 目錄
# 解壓后的lib/*.ko為各種驅(qū)動
<font color=#ff0000>8k: 如何將特定驅(qū)動添加到initrd中?</font>
# 1. 官網(wǎng)下載驅(qū)動
# 2. 編譯驅(qū)動: /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
# 模塊名 # 此處不可接絕對路徑,
# 且內(nèi)核版本要與上面編
# 譯的驅(qū)動放置的內(nèi)核目
# 錄是同一個才行
模塊參數(shù)調(diào)優(yōu) (parm)
# 系統(tǒng)真實放置模塊的位置:
/lib/modules/$(uname -r)/kernel/drivers/
lsmod ext4
# 模塊名 模塊大小 模塊使用次數(shù) 模塊描述
Module Size Used by
ext4 579979 0
mbcache 14958 1 ext4
jbd2 107478 1 ext4
modinfo ext4 # 查看模塊的詳細(xì)信息
# 部分模塊有一個參數(shù): parm, 可用于調(diào)優(yōu)
# redhat5有/etc/modprobe.conf, 可直接在此文件內(nèi)添加內(nèi)容:
options snd-card-0 index=0 # 調(diào)整模塊參數(shù)
# 但redhat6開始需要在/etc/modprobe.d/下新建*.conf文件, 用于調(diào)優(yōu)模塊參數(shù):
vi /etc/modprobe.d/st.conf
options st buffer_kbs=128 # 特別注意, 模塊名和參數(shù)不可以寫錯!
# 修改模塊參數(shù)后如何驗證參數(shù)生效?
# 方法一:
# 修改后重載st模塊, 然后去/sys/目錄下查看參數(shù)是否生效
# 方法二:
modprobe --showconfig 模塊名
<font color=#ff0000>8k: 重建ram disk文件, 解決P2V問題</font>
- P2V問題: 物理機遷移到虛擬機時系統(tǒng)無法啟動
# 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文件中的內(nèi)容:
/usr/lib/dracut/skipcpio /tmp/initramfs-...img | zcat | cpio -id
小白式系統(tǒng)調(diào)優(yōu) (redhat7)
tune: n,v 曲調(diào); 調(diào)整
/usr/lib/tuned/
下有可調(diào)參數(shù)
yum -y install tuned
systemctl enable tuned && systemctl start tuned
tuned-adm list # 列出所有可以調(diào)優(yōu)的參數(shù)
tuned-adm profile throughput-performance # 系統(tǒng)調(diào)優(yōu), 選用throughput-performance
tuned-adm list # 馬上生效且重啟有效
自定義某些配置:
cd /usr/lib/tuned/
cp -r throughput-performance/ my442 # 新建自定義目錄
vi my442/tuned.conf # 修改配置你需要的參數(shù)
tuned-adm profile mu442 # 讓你配置的參數(shù)生效
系統(tǒng)資源限制調(diào)優(yōu)
# 編輯完limit.conf文件, 立即生效
rss - max resident set size (KB) # 常駐內(nèi)存(物理), 無法限制
as - address space limit (KB) # 虛擬內(nèi)存, 可做限制
# 用戶可自己調(diào)整限制至最大值: 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默認(rèn)不裝, redhat7安裝)
redhat6中如何利用cgroup對系統(tǒng)資源做限制:
yum -y install libcgroup
/etc/init.d/cgconfig start # 服務(wù)啟動后系統(tǒng)就有/cgroup/這個目錄
- 臨時生效:
# /cgroup/內(nèi)控制資源, 可在其內(nèi)新建目錄, 將需要控制的進程對應(yīng)的PID寫入新建目錄內(nèi)的tasks文件中
mkdir /cgroup/memory/{bigdata,rh442} # 想對bigdata, rh442的內(nèi)存做限制,
# 就在/cgroup/memory/目錄下新建目錄
echo 102400000 > /cgroup/memroy/rh442/memory.limit_in_bytes # 可通過此方式臨時對rh442組的
# 內(nèi)存做限制, 只能用100M內(nèi)存
echo $(pidof vsftpd) > /cgroup/memory/rh442/tasks # 將需對內(nèi)存做限制的進程的PID寫入rh442組
# 的tasks中, 這樣就對對應(yīng)進程做了限制
pmap PID # 查看進程使用內(nèi)存情況, 可以看到一個進程運行時一共需要的內(nèi)存
# 如何刪除內(nèi)存中的文件夾:
rmdir rh442
- 永久生效: <font color=#ff0000>可對云, 虛擬機, docker等容器使用的資源做限制</font>
vi /etc/cgconfig.conf # 添加如下內(nèi)容:
group bigdata { # bigdata為需要限制的組的組名, 名字可自定義, 可以創(chuàng)建多個group
blkio { # blkio為需要限制的內(nèi)容
參數(shù) = "值"; # 可以限制的參數(shù)能在/cgroup/blkcio/目錄下找到
}
memory {
參數(shù) = "值";
memory.limit_in_bytes = "100M";
}
}
/etc/init.d/cgconfig restart
# 注: 如果這樣配置后在/cgroup/memory/內(nèi)執(zhí)行重啟命令, 會報錯: Device or resource busy
# 故需要到其他無關(guān)目錄內(nèi)重啟, 才會成功
# 這樣配置以后重啟cgconfig服務(wù), 會在/cgroup/memory/目錄下創(chuàng)建文件夾bigdata和memroy,
# 但還沒針對服務(wù)做限制, 因此還需進行下面步驟
vi /etc/cgrules.conf # 策略文件, 添加上述參數(shù)對應(yīng)的配置:
#用戶:命令 需要限制的內(nèi)容 組名
*:cp blkio,memory bigdata/redhat/ # group內(nèi)有子組時, 可在bigdata后面添加redhat
# 上面這行的含義為對所有用戶執(zhí)行cp命令時, 會使用bigdata內(nèi)關(guān)于memory和blkio做限制的參數(shù)
# 在/etc/cgconfig.conf對內(nèi)存做了100M的限制, 因此超出100M時不會執(zhí)行cp命令
*:bigmem memory bigdata/ # 命令最好是絕對路徑
*:/etc/init.d/vsftpd memory bigdata/ # 針對服務(wù)做限制
/etc/init.d/cgred restart
# 也可用以下命令重啟服務(wù):
service cgconfig restart
service cgred restart
redhat7中如何利用cgroup對系統(tǒng)資源做限制:
書本P98, P99
- redhat7內(nèi)可針對服務(wù)或用戶做限制
軟件包: memload (類似于bigmem), 可用作測試內(nèi)存
memload 256
: 單位M, 申請使用256M內(nèi)存
man system.resource-control # 查看可以用來限制的參數(shù)
/etc/systemd/system/ # 此目錄下針對服務(wù)做限制
/etc/systemd/user/ # 此目錄下針對用戶做限制
# 實例: 需限制nginx.service的內(nèi)存使用量為512M
cd /etc/systemd/system/
mkdir nginx.service.d # 新建需要限制的服務(wù)對應(yīng)的目錄
vi 00-limit.conf # 新建00-limit.conf文件, 添加以下內(nèi)容:
[service]
MemoryLimit=512M
systemctl daemon-reload # 然后重載以及重啟服務(wù), 限制即可生效
systemctl restart nginx
硬件監(jiān)控
CPU
基本概念:
- 一個核就是一個cpu
- 核與線程:
- 單線程: 人腦處理任務(wù)
- 多線程: 電腦處理2個任務(wù)
- 隊列: 10個任務(wù)同時來
衡量cpu性能:
-
lscpu | grep BogoMIPS
:BogoMIPS: 5616.00
每秒處理百萬指令集的數(shù)目, 5616 * 1000,000
-
lscpu | grep "L3 cache"
- L3 cache: 6144K
cpu <-- FSB --> mem: cpu和內(nèi)存之間通過 FSB (前端總線) 交換數(shù)據(jù)
UMA: 一致性內(nèi)存訪問
-
NUMA: 非一致性內(nèi)存訪問, cpu和mem在同一個NUMA node中
- 優(yōu): 減少前端總線的壓力
- 缺: 開啟NUMA無法內(nèi)存復(fù)用
- L1: 一級緩存, 一般CPU的L1i和L1d具備相同的容量
- L1d: 數(shù)據(jù)緩存 (Data Cache, D-Cache)
- L1i: 指令緩存 (Instruction Cache, I-Cache)
- L2: 二級緩存
- L3: 三級緩存
為什么CPU緩存會分為一級緩存L1、L2前塔、L3懒熙?有什么意義?
- Virtualization type: full (支持全虛擬化)
# 更加詳細(xì)的關(guān)于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 的物理內(nèi)存以及 2^42 = 4TB 的虛擬內(nèi)存
內(nèi)存
dmidecode # 查看內(nèi)存信息, 如條數(shù), 大小, 插槽, 頻寬, 電壓, 是否支持NUMA等
numactl # 設(shè)置cpu和內(nèi)存在哪個NUMA node中
存儲
SATA | SAS | SSD | |||
---|---|---|---|---|---|
容量 | > | > | |||
性能 | < | < |
常用RAID Level:
1 | 5 | 10 |
---|---|---|
裝系統(tǒng) | 分布式 |
-
RAID5:
-
帶奇偶校驗的條帶化, 有寫懲罰
- 大寫: > 一半, 讀整個分條, 寫回 P
- 小寫: < 一半
- 適用場景: 順序的大IO ( 如視頻監(jiān)控, 備份, OLAP )
-
-
RAID10:
- 使用場景: 隨機的小IO ( 如數(shù)據(jù)庫OLTP, 事務(wù)型, 交易系統(tǒng) )
FC - SAN: 一般用于公司內(nèi)部業(yè)務(wù), 距離有限
IP - SAN: 熱備
網(wǎng)絡(luò)
- 網(wǎng)卡選型
- 組網(wǎng) ( GE/10GE/IB ) 40Gb/56Gb/100Gb
- 雙網(wǎng)卡綁定模式 ( mode = 0-6 ) 0: 輪循 1: 主備 4: LACP 6: 最佳, 計算最小負(fù)載, 然后分發(fā)數(shù)據(jù)包至最小負(fù)載那里
- VLAN
- 網(wǎng)卡是否支持虛擬化: 指令集: VT-d(直通模式, 運算在網(wǎng)卡中進行), VT-x, SR-IOV(單根IO虛擬化, 硬直通, 直通虛擬機網(wǎng)卡)
cat /var/log/dmesg # 記錄啟動時的硬件信息
dmesg | grep eth # 可用于判斷內(nèi)核是否識別網(wǎng)卡
[ 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>系統(tǒng)啟動時, 紅字之后的是服務(wù)和文件系統(tǒng)的信息 !!!</font>
生產(chǎn)環(huán)境中可能遇到的問題以及一些補充說明
書本P115:
系統(tǒng)啟動時顯示: [<fffff...f 8014ebaf>]kobject_add+0x170/0x196
<font color=#ff0000>一般是物理機的內(nèi)存不兼容或者硬件問題造成的.</font>
lscpu, lspci, lsusb
# getconf此命令一般用于將系統(tǒng)配置變量值寫入標(biāo)準(zhǔn)輸出, 本身是個ELF可執(zhí)行文件汹桦,也可以用于獲取系統(tǒng)信息
getconf -a | grep -i page # 查看系統(tǒng)內(nèi)存分頁大小
# 內(nèi)存頁: 內(nèi)存最小單元 (類比與block塊的大小), 本例為4K
PAGESIZE 4096
PAGE_SIZE 4096
-a # 獲取全部系統(tǒng)信息
dmidecode --from-dump 文件名 > dmi.txt # 分析二進制文件
# 可分析出L1, L2的大小, 注意內(nèi)核個數(shù)!
影響磁盤IO性能的因素
- 機械硬盤:
- 轉(zhuǎn)數(shù)
- 尋道時間
存儲密度
<font color=#ff0000>分區(qū)號越低, 越靠近外環(huán)</font>
讀性能提升
讀預(yù)取 (順序讀):
- 固定預(yù)取
- 倍數(shù)預(yù)取
- 智能預(yù)取
-
/sys/block/sda/queue/read_ahead_kb
--> 4096 KB, 可調(diào)整此參數(shù)提升讀預(yù)取的大小
-
- 不預(yù)取
寫性能提升
硬盤調(diào)優(yōu)的角度(可針對某塊硬盤):
- 方法一:
/sys/block/sda/queue/nr_requests
隊列長度 - 方法二:
/sys/block/sda/queue/scheduler
調(diào)度算法-
noop [deadline] cfq
, 中括號中為當(dāng)前使用的調(diào)度算法 - 調(diào)整:
echo noop > /sys/block/sda/queue/scheduler
-
調(diào)度算法:
-
deadline 最終期限
- <font color=#ff0000>適合小IO和ext4文件系統(tǒng)</font>
-
noop 沒有任何調(diào)優(yōu)
- <font color=#ff0000>存儲映射時無需調(diào)優(yōu)</font>
-
as 猜想時間
- <font color=#ff0000>適合大IO和xfs文件系統(tǒng)</font>
-
cfg 給每個應(yīng)用不同大小
iostat # 對一個程序設(shè)置或獲取I/O調(diào)度級別和優(yōu)先級 ionice -p 1 # 查看PID為1的進程的I/O調(diào)度級別以及優(yōu)先級 ionice -p 1 -c 1 -n 2 # 設(shè)置PID為1的進程為class1, nice值為2
-c參數(shù):
class | 1 | 2 | 3 | ||
---|---|---|---|---|---|
優(yōu)先級 | > | > | |||
實時: 先進先出 | 輪循: n越小, 分到的時間片越多, 但每個進程都會輪到 | 空閑 |
- -n參數(shù):
- 0 - 7, 越小越重要, 優(yōu)先級越高
mailload.py 壓力測試工具
<font color=#ff0000>當(dāng)然也可以通過tuned.conf修改參數(shù)進行調(diào)優(yōu)</font>
進程管理和調(diào)度
ps axo %cpu,%mem,nice,psr
nice # 查看進程的優(yōu)先級
psr # 顯示程序與運行在哪個cpu上
優(yōu)先級:
- 靜態(tài): 1 - 99, 數(shù)字越大, 優(yōu)先級越高
- 動態(tài): 0 <=> 100 - 129 ( -20 - 19 )
chrt -p 1 # 實時查看PID為1的進程優(yōu)先級
pid 1's current scheduling policy: SCHED_OTHER
pid 1's current scheduling priority: 0
<font color=#ff0000>FIFO和RR謹(jǐn)慎使用, 因為一旦使用會將整個CPU占用 !!!</font>
-
SCHED_FIFO
- 先進先出, first input first output, 優(yōu)先級 1 - 99
- 優(yōu)先級高的會搶占cpu
-
chrt -f 10 dd if=/dev/zero of=/dev/null
:實時設(shè)置FIFO且優(yōu)先級為10
-
SCHED_RR
- 類似FIFO但有時間片的概念
chrt -r 20 dd if=/dev/zero of=/dev/null
- 只有RR級別才會輪循, 優(yōu)先級越高, 分到的時間片越多
-
SHCED_OTHER
nice
renice
-
other如何獲得更長的時間片?
方法一: 類似cgroup中的內(nèi)存管理去設(shè)置 CPUShares=128 (份額 = 2的倍數(shù)), 永久生效
方法二:
systemctl set-property httpd.service CPUShares=512
, 臨時生效
# 如何對已運行的程序調(diào)整優(yōu)先級:
chrt -p 2420
chrt -p -f 10 2420 # 對PID為2420的進程調(diào)整優(yōu)先級為FIFO, 10
跟蹤系統(tǒng)和庫調(diào)用
系統(tǒng)調(diào)用
<font color=#ff0000>排錯時會用到 !</font>
strace -c ls -l # 計數(shù)每步的操作時間
-c # count
strace -e read cp -r /etc/ /data/ # 查看read的具體操作
strace -p PID # 實時查看某程序的系統(tǒng)和庫的調(diào)用情況
庫調(diào)用
ltrace cp # 查看某個命令會調(diào)用哪些庫
減少磁盤訪問次數(shù)
- VFS: 虛擬文件系統(tǒng), 對應(yīng)用而言, 只要調(diào)用驅(qū)動, 寫入數(shù)據(jù)就好了, 所以任何的文件系統(tǒng)對應(yīng)用來講都是VFS
tune2fs -l /dev/vda1 # 查看原數(shù)據(jù), 簡略
dumpe2fs /dev/vda1 # 詳細(xì)
# 可以看到元數(shù)據(jù)中由block group, 即分組的概念, 以此保證數(shù)據(jù)連續(xù)
<font color=#ff0000>8K: 超級塊損壞時如何修復(fù)? 一定要記得先卸載分區(qū)再修復(fù) !!!</font>
dd if=/dev/zero of=/dev/vda1 bs=1k count=20 # 模擬生產(chǎn)環(huán)境中超級塊損壞的情況, 此處為破壞超級塊
# 修復(fù)ext類型文件系統(tǒng):
# 方法一:
umount /dev/vda1
fsck -v /dev/vda1 # 一直yes
# 方法二:
umount /dev/vda1
e2fsck -b 98304 /dev/vda1 # 使用98304的超級塊來恢復(fù),
# 特別注意, 不同的文件系統(tǒng), 超級塊的位置固定的
# 修復(fù)xfs類型文件系統(tǒng):
xfs_repair /dev/vda1
日志型文件系統(tǒng)
ext3/ext4/xfs/NTFS
優(yōu): 減少開機掃描
缺: 寫數(shù)增加( 兩次寫: 1. journal 2.inode )
外部日志區(qū)如何配置
條件:
- (1) journal size =2^N < 400M
- (2) 整個分區(qū)只能用于journal device, 不能用作其他
- <font color=#ff0000>多個文件系統(tǒng)可以共用一個外部日志區(qū), 不過block size必須相同</font>
- (3) journal block size 必須與源文件系統(tǒng)一致
現(xiàn)在有兩塊硬盤, sda1和sdb1, 需要將sdb1用作sda1的外部日志區(qū), 從而減少硬盤訪問次數(shù), 下面為配置方法:
# 1. 卸載文件系統(tǒng)
umount /dev/sda1
umount /dev/sdb1
# 2. 查看文件系統(tǒng)的block大小及日志位置
dumpe2fs /dev/sda1 | egrep -i (journal|size)
# 3. 在已存在的文件系統(tǒng)中刪除內(nèi)部日志
tune2fs -O ^has_journal /dev/sdb1
# 4. 創(chuàng)建一個擴展的日志設(shè)備
mke2fs -O journal_dev -b block_size /dev/sdb1
# 5. 更新文件系統(tǒng)的超級塊, 從而使用擴展的日志
tune2fs -j -J device=/dev/sdb1 /dev/sda1
cpu的IRQ均衡 (IRQ balance)
<font color=#ff0000>用來均衡cpu的訪問次數(shù), 但cpu的緩存效果會減弱</font>
- 每個硬件都會對應(yīng)一個中斷號, 一般IRQ只會指向某一個cpu, 所以某個設(shè)備只會在使用對應(yīng)的cpu跑任務(wù), 即只在某個cpu上消耗資源
cat /proc/interrupts
中斷號 | 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 (不均衡)
- 一般應(yīng)用程序運行的時候會在不同的cpu上來回切換:
ps axo %cpu,%mem,psr
- 優(yōu): 設(shè)置應(yīng)用程序運行在指定的某個cpu或某些cpu上, 提高緩存命中率, 從而提升性能
- 缺: 不均衡的運行隊列會導(dǎo)致較長的等待時間, 一般用于NUMA架構(gòu)
taskset -p PID # 查看PID的進程運行在哪個cpu上
taskset -p 3 PID # 此處的3為16進制, 例如1, 2, 4, 8, f
cpu隔離
如何做cpu隔離, 實現(xiàn)某個cpu只運行特定程序?
# 1. 啟動時編輯/etc/grub.conf, 隔離cpu
isolcpus=cpu_number,cpu_number,... # 設(shè)定只使用某幾個cpu, 其他不用
# 2. 設(shè)定某個程序運行在特定cpu上
taskset -p cpu_number PID
# 3. 考慮調(diào)整IRQ親緣
cpu支持熱插拔
- CPU0以外的cpu支持如拔插, 0號不支持的原因是因為它是啟動cpu
- 支持熱拔插的前提: 硬件支持 (BIOS支持物理熱拔插)
- 對NUMA系統(tǒng)非常有用
- 熱拔插的操作后內(nèi)核會動態(tài)更新
/proc/cpuinfo
及其他文件內(nèi)的信息 see kernel-doc-*/Documentation/cpu-hotplug.txt
# 1. 查看cpu號
grep processor /proc/cpuinfo
cat /proc/interrupts
# 2.動態(tài)關(guān)閉某個cpu, 如cpu1
echo 0 > /sys/devices/system/cpu/cpu1/online # online: 相當(dāng)于一個開關(guān)
cat /proc/interrupts # 關(guān)閉后無法看到cpu1的信息
# 3. 重開cpu1
echo 1 > sys/devices/system/cpu/cpu1/online
cat /proc/interrupts # 再次可以看到cpu1的信息
注: cpu1在被關(guān)閉時已有程序在上面運行, 關(guān)閉時其上的程序會被遷移到其他cpu, 不會影響原來程序的運行, 就算指定某程序在cpu1上運行, 當(dāng)cpu1被關(guān)閉時, 該程序依舊不會受到影響, 同樣會被遷移到其他cpu上, 但cpu1再次被開啟時, 原來指定的程序不會再次回到cpu1上運行
調(diào)度域 (scheduler domains)
cpuset: 進程組, 支持多核和NUMA架構(gòu)
/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 # 包含的內(nèi)存zone
cat tasks # 包含的所有任務(wù)
此架構(gòu)用于NUMA特別方便:
mkdir {rh442,cl210}
echo 0-1 > rh442/cpuset.cpus # 每個cpuset至少包含一個cpu和一個內(nèi)存zone
echo 0 > rh442/cpuset.mems
echo 2-3 > cl210/cpuset.cpus # cpuset支持嵌套, 故可將 2-3 改為 0-1
echo 0 > cl210/cpuset.mems
# 關(guān)閉cpu嵌套, 注意需要先關(guān)閉根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 # 查看到結(jié)果為/rh442
cd /proc/1
cat cpuset # 查看到結(jié)果為/, 根cpuset包含所有系統(tǒng)資源
內(nèi)存管理(地址和分配)
- 虛擬內(nèi)存
- 應(yīng)用程序申請的內(nèi)存 (按需分配)
- 應(yīng)用程序申請?zhí)摂M內(nèi)存時時, 總認(rèn)為<font color=#ff0000>每一個程序都有一段線性的, 連續(xù)的地址空間, 但實際映射到的物理內(nèi)存上是不連續(xù)的</font>
- 地址范圍從0到最大值
- 32bits架構(gòu)的系統(tǒng), 內(nèi)存最大支持 2^32 = 4GB
- 64bits架構(gòu)的系統(tǒng), 內(nèi)存最大支持 2^48 = 256TB, 但由于內(nèi)核與硬件的限制, 實際只支持到 2^42 = 4TB
- 用內(nèi)存頁來表示
- 物理內(nèi)存
- 物理內(nèi)存 = 內(nèi)存 + swap, 即 96G = 64G + 32G
- swap上的數(shù)據(jù)只做暫存, 不作處理
- cpu的內(nèi)存管理單元 MMU: 負(fù)責(zé)管理虛擬內(nèi)存與物理內(nèi)存之間的映射關(guān)系
- 物理內(nèi)存 = 內(nèi)存 + swap, 即 96G = 64G + 32G
ps aux | less # 可以查看到虛擬內(nèi)存VSZ和物理內(nèi)存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虛擬內(nèi)存
watch -n 1 'cat /proc/meminfo | grep AS' # AS:地址空間
- PTE: 頁表條目 (page table entries)
- 記錄虛擬內(nèi)存到物理內(nèi)存的映射關(guān)系
- TLB: 記錄PTE內(nèi)映射關(guān)系的緩存
- Hugepage (大頁): 用于存放TLB的緩存數(shù)據(jù)
cat /proc/meminfo | grep -i huge
-
bigmem -H NUM
: -H, 指定使用Hugepage, 此命令可用作測試大頁 - 一旦分配了大頁, 其他應(yīng)用程序無法申請到大頁使用的內(nèi)存
- Hugepage (大頁): 用于存放TLB的緩存數(shù)據(jù)
內(nèi)存架構(gòu)
x86, 即32bits的系統(tǒng)上:
1024M, 具體分配如下 | 物理內(nèi)存的第一個GB分配給內(nèi)核使用 (直接映射內(nèi)存) |
---|---|
128M | 高位內(nèi)存, 用于存放PTE |
896M, 包括下面的1M和16M和879M | |
1M | 給BIOS和IO設(shè)備使用 |
16M | 給DMA (直接內(nèi)存訪問) 使用 |
879M | 低位內(nèi)存 |
x86_64, 及64bits的系統(tǒng)上:
128T | 系統(tǒng)使用 |
---|---|
128T | 應(yīng)用使用 |
頁中斷 (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
- 次頁中斷
- 由物理內(nèi)存分配
- 主頁中斷
- 由swap分配
- 主頁中斷越多, 系統(tǒng)性能越差
頁:
(1) dirty page: 內(nèi)存中已被修改, 還未寫入磁盤的數(shù)據(jù), 可用sync
命令將drity page的數(shù)據(jù)寫入磁盤
(2) clean page: free -m
中的caches, 以寫入磁盤, 但是作為緩存, 提升讀性能的數(shù)據(jù)
生產(chǎn)環(huán)境中一個特別有用的參數(shù): <font color=#ff0000>vm.swappiness</font>
vm.swappiness
默認(rèn)值的范圍在: 0 - 100
- 此值越高, 越多的使用swap
- 此值越低, 越多的使用內(nèi)存
sysctl -a | grep swappiness
vm.swappiness = 30
生產(chǎn)環(huán)境中, 若swap使用過多, 如何更多的使用內(nèi)存, 減少swap的使用量:
# 方法一: 臨時生效
sysctl -w vm.swappiness=20
# 方法二: 永久生效
vi /etc/sysctl.conf
vm.swappiness = 20
sysctl -p
如果需要清空swap中的緩存, 該怎么做?
# 先看看當(dāng)前swap和內(nèi)存的使用情況: 如果swap使用量已經(jīng)超過內(nèi)存的空閑量, 則無法被清空!
swapon -s
Filename Type Size Used Priority
/dev/sda1 partition 8257532 8257532 -1
swapoff /dev/sda1 # 一定要注意, 生產(chǎn)環(huán)境中千萬不要隨便去卸載swap!!!
watch -n 1 'free -m'
擴展swap
一些概念:
冷數(shù)據(jù), anon (匿名頁, 可用命令
pmap
查看) 都會大量放于swap中.一般內(nèi)存越大, swap也分配的越大, 因為內(nèi)存中的冷數(shù)據(jù)也越多.
如何提升swap的性能:
- 將swap分到不同的硬盤上
- 分配分區(qū)號小的分區(qū), (分區(qū)號越小, 越靠近外圈, 磁頭每轉(zhuǎn)過一圈讀取到的數(shù)據(jù)越多)
方法一: 使用硬盤分區(qū)
<font color=#ff0000>注: swap分區(qū)Priority的值越大, 優(yōu)先級越高, 越先被使用!</font>
# (1) 先在不同的兩塊硬盤上都分出1個分區(qū), 都用作swap
fdisk /dev/sdb # 分出/dev/sdb1
fdisk /dev/sdc # 分出/dev/sdc1
# (2) 然后格式化
mkswap /dev/sdb1
mkswap /dev/sdc1
# (3) 編輯/etc/fstab, 注意調(diào)整各自的優(yōu)先級, 做到均衡使用兩個分區(qū)的swap (即輪循)
vi /etc/fstab # UUID可用命令blkid查看
UUID="..." swap swap defaults,pri=-2 0 0
UUID="..." swap swap defaults,pri=-2 0 0
方法二: 使用文件
RHCE課程中已學(xué)過, 此處不再贅述.