基本概念
QPS:query per second, 1秒內完成的請求數
RT:response time, 1個請求完成的時間
Throughput越大,Latency會越差。因為請求量過大,系統太繁忙,所以響應速度自然會低
Latency越好,能支持的Throughput就會越高。因為Latency短說明處理速度快,于是就可以處理更多的請求
最佳線程數量=((線程等待時間+線程cpu時間)/線程cpu時間) * cpu數量
線程過多,時間消耗長,并不是說代碼執行效率下降了,而是資源的競爭,導致線程等待的時間上升了,線程越多消耗內存越多,過多的線程直接將系統內存消耗殆盡
平均響應時間 = (并發線程數/最佳線程數) * 最佳線程數的響應時間
總QPS=線程數*單個線程的QPS
CPU監控與調優
系統負載
系統負載:可運行(運行中或者等待CPU調度)或不可中斷(等待IO)的進程數
uptime
load average: 2.03, 20.17, 15.09
表示過去1分鐘、5分鐘、15分鐘的系統負載情況
多核情況下,真實的負載是需要除去CPU個數,如load為1,在1個CPU時,是滿的,在2個CPU時,是50%
如果Load Average高,但CPU的us、sy使用率低,這時要看一下磁盤IO或網絡IO的等待時間(等待進程包括等待CPU時間片和等待IO(不可中斷),等待IO的進程的狀態為“D”,可以通過ps aux的state列進行查看,磁盤的IO等待可以通過iostat -x查看,主要看await, svctm列)
使用率
使用率分為:us(用戶)、sy(系統)、id(空閑)、wa(IO等待)、ni(通過nice命令改變過優先級)、hi(硬中斷)、si(軟中斷)、st(虛擬機)
如果在多核的機器俠,使用率有可能超過100%,也存在多個進程加起來后超過100%的情況
一般us:65%-70%,sy:30%-35%,idle:0%-5%,證明CPU被充分使用和均衡
如果wa很高,就需要看一下磁盤I/O
如果wa很低,id很高,但系統還是很慢,那就要查一下網絡IO或者遠程服務器的回應是不是很慢,或者查一下上下文切換和鎖,看看是否存在大量的鎖爭用和等待的情況
監控工具:top, vmstat
查看某個進程的使用率
while :; do ps -eo pid,ni,pri,pcpu,psr,comm | grep ‘mysqld’; sleep 1;
找到消耗CPU最多的前10個進程
ps -eo pcpu,pid,user,args | sort -k 1 -r | head -10
找到消耗內存最多的前10個進程
ps -auxf | sort -nr -k 4 | head -10
運行隊列大小
一個進程可以有running,runnable,block(等待IO或者系統調用)
運行隊列是指runnable(等待運行)的進程數
每個處理器的運行隊列大小不應超過3個,少于10倍的CPU個數,否則線程過多或者CPU不夠
監控工具:vmstat(procs下的r列)
上下文切換
- 上下文
進程運行時的寄存器和CPU緩存等 - 保存位置
進程描述符和內核堆棧 - 發生時機
IO操作、資源同步、優先級搶占、時間片到達、軟硬中斷
時鐘中斷:每隔一段時間就會發生一次時鐘中斷(切換),可以通過以下辦法判斷時鐘中斷的頻率
cat /proc/interrupts | grep timer
...wait 10s...
cat /proc/interrupts | grep timer
將兩個結果值相減然后除以10,則得到每秒因時鐘中斷發生的切換數,如果系統的上下文切換數比該值大,則有可能發生了IO操作或者資源爭用或者sleep等
- 主動切換
鎖爭用、調用系統函數 - 被動切換
除主動切換之外的切換
監控工具:vmstat(system下的cs列)
更多描述可參考Context Switching, Some Resources
鎖爭用
主要是監控主動切換
監控工具:pidstat -w -I -p [pid] seconds的cswch/s列
統計的是全部核的總切換數,占用率=count/核數*80000/CPU時鐘數,通常一次切換消耗80000次時鐘頻率,如假設當前切換數是3500,CPU為雙核的3.0GHz,那么上下文切換占用的CPU率為:(3500/2)*80000/3000000000=4.7%
如果切換率超過5%,則證明程序存在鎖爭用;如果在3%-5%之間,則要注意,可能存在鎖爭用
線程遷移
一個線程最好在同一個CPU中運行,因為緩存等可以重新利用,如果因為一個CPU忙而無法運行,然后將線程遷移到其他的核,則要重新加載緩存,造成性能損耗
快速監控
通過vmstat查看整體CPU使用情況
top查看CPU占用高的幾個進程
pidstat查看這幾個進程對應的線程
調優
- 確保沒有沒用的進程在運行(ps -ef)
- 檢查可運行隊列,確定每個CPU不超過3個,如果過多,要不就減少線程數,要不就把應用遷移到其他機器上或者增加CPU
- 確定CPU利用率中user/system的比例維持在70/30,當system的利用率比較高時,要查看是IO中斷還是鎖競爭,同時檢查wa(IO等待)的比例是否過高
- 調高關鍵進程的優先級,將非關鍵的,但使用CPU較多的進程的優先級降低
- 將進程綁定到特定的CPU(CPU親近性),減少CPU緩存的失效
- 將產生大量中斷的進程綁定到一個固定的CPU上
- 修改程序,增加并行性
內存監控與調優
內存主要看可用內存大小、SWAP空間大小、頁面換入換出頻率
free -m
total used free shared buffers cached
Mem: 2887 2789 97 0 26 1177
-/+ buffers/cache: 1585 1301
Swap: 0 0 0
- Mem:物理內存統計
字段 | 說明 |
---|---|
total | 物理內存總量 |
used | 已分配的內存(包含buffers與cache),但其中可能部分緩存并未實際使用 |
free | 未被分配的內存 |
shared | 共享內存 |
buffers | 系統分配但未被使用的buffers的數量,針對磁盤塊數據的cache,塊設備的讀寫緩沖區 |
cached | 系統分配但未被使用的cache的數量,針對文件的cache |
- -/+ buffers/cache
字段 | 說明 |
---|---|
used | 實際使用的內存總數, 第一行的used - buffers - cached |
free | 實際剩余的內存總數, 第一行的free + buffers + cached |
Linux會盡量使用盡可能多的內存,如果存在足夠的內存,Linux會對經常被訪問的文件進行緩存(cached),同時在進行IO操作時,Linux會使用塊緩存機制(buffers),加快IO處理
所以一般查看內存還剩余多少,要查看free的第二行參數
- swap:交換分區大小
swap空間的大小并不能表明內存存在瓶頸,因為如果一個進程空閑了,Linux會把它換出到磁盤
主要是要看頁面換入換出的大?。╲mstat的si、so列)
如果可用內存不多,有大量的頁面交換活動,則要考慮加內存;(每秒有200-300的頁面換入或換出則代表內存存在瓶頸)
如果仍有很多內存,但有頁面活動,則代表系統沒有頁面交換,而可能是正在加載程序
調優
- 增大內存
- 使用大頁、大的TLB,特別適合于數據庫服務器
- 創建一個或多個單獨的swap分區
- 調整swap寫到硬盤的參數:vm.swappiness, vm.dirty_background_ratio, vm.dirty_ratio
磁盤監控與調優
只顯示磁盤信息,以M為單位,顯示擴展信息,n代表多少秒輸出一次
iostat -dmx n
Device: rrqm/s wrqm/sr/s w/s rMB/swMB/s avgrq-sz avgqu-sz await svctm %util
sda 0.11 33.49 0.27 26.820.00 0.24 18.16 0.10 3.68 0.67 1.82
字段 | 描述 |
---|---|
rrqm/s | 隊列中每秒鐘合并的讀請求數量(當系統調用需要讀取數據的時候,VFS將請求發到各個FS,如果FS發現不同的讀取請求讀取的是相同Block的數據,FS會將這個請求合并Merge) |
wrqm/s | 隊列中每秒鐘合并的寫請求數量 |
r/s | 每秒鐘完成的讀請求數量 |
w/s | 每秒鐘完成的寫請求數量 |
rMB/s | 每秒鐘讀取的數量,讀IOPS=(rMB/s) / (r/s),IOPS:一次磁盤的連續讀或者連續寫稱為一次磁盤 I/O,隨機讀寫頻繁的應用的關鍵衡量指標,IOPS = 1s/(尋道時間+旋轉延遲+數據傳輸時間) |
wMB/s | 每秒鐘寫入的數量,寫IOPS=(wMB/s) / (w/s) |
avgrq-sz | 平均請求扇區的大小,平均每次請求的大小,avgrq-sz < 32K 隨機存取為主。 avgrq-sz > 32K 順序存儲為主 |
avgqu-sz | 平均請求隊列的長度,此值越小越好,avgqu-sz > 2 可以認為存在I/O性能問題 |
await | 平均每次請求的等待時間,單位毫秒,一般系統IO響應時間應該低于5ms,如果大于10ms就比較大了。等待時間包括了隊列時間和服務時間,await和svctm越接近越好,代表幾乎無需等待,反之差值越大,隊列的時間越長,應用得到的響應時間變慢, 還可參考vmstat結果b參數(等待資源的進程數)和wa參數(IO等待所占用CPU時間百分比) |
svctm | 平均每次請求的服務時間,即磁盤讀或寫操作執行的時間,包括尋道,旋轉時延,和數據傳輸等時間。(尋道時間:是指將讀寫磁頭移動至正確的磁道上所需要的時間。尋道時間越短,I/O操作越快,目前磁盤的平均尋道時間一般在3-15ms。旋轉延遲: 是指盤片旋轉將請求數據所在扇區移至讀寫磁頭下方所需要的時間。旋轉延遲取決于磁盤轉速,通常使用磁盤旋轉一周所需時間的1/2表示。比如,7200 rpm的磁盤平均旋轉延遲大約為60*1000/7200/2 = 4.17ms,而轉速為15000 rpm的磁盤其平均旋轉延遲約為2ms。數據傳輸時間: 是指完成傳輸所請求的數據所需要的時間,它取決于數據傳輸率,其值等于數據大小除以數據傳輸率。目前IDE/ATA能達到133MB/s,SATA II可達到300MB/s的接口數據傳輸率,數據傳輸時間通常遠小于前兩部分消耗時間,簡單計算時可忽略。) (r/s+w/s)*(svctm/1000)=util,如果util達到100%,那么此時svctm=1000/(r/s+w/s),假設IOPS是1000,那么svctm大概在1毫秒左右,如果長時間大于這個數值,說明系統出了問題。 |
util | 設備的利用率,如果util接近100%,則說明設備的能力趨向于飽和(如果是多磁盤,即使%util是100%,因為磁盤的并發能力,所以磁盤使用未必就到了瓶頸) |
每個參數的理解可以參考下面的圖片
上圖的左邊是iostat顯示的各個性能指標,每個性能指標都會顯示在一條虛線之上,這表明這個性能指標是從虛線之上的那個讀寫階段開始計量的,比如說圖中的w/s從Linux IO scheduler開始穿過硬盤控制器(CCIS/3ware),這就表明w/s統計的是每秒鐘從Linux IO scheduler通過硬盤控制器的寫IO的數量。
結合上圖對讀IO操作的過程做一個說明,在從OS Buffer Cache傳入到OS Kernel(Linux IO scheduler)的讀IO操作的個數實際上是rrqm/s+r/s,直到讀IO請求到達OS Kernel層之后,有每秒鐘有rrqm/s個讀IO操作被合并,最終轉送給磁盤控制器的每秒鐘讀IO的個數為r/w;在進入到操作系統的設備層(/dev/sda)之后,計數器開始對IO操作進行計時,最終的計算結果表現是await,這個值就是我們要的IO響應時間了;svctm是在IO操作進入到磁盤控制器之后直到磁盤控制器返回結果所花費的時間,這是一個實際IO操作所花的時間,當await與svctm相差很大的時候,我們就要注意磁盤的IO性能了;而avgrq-sz是從OS Kernel往下傳遞請求時單個IO的大小,avgqu-sz則是在OS Kernel中IO請求隊列的平均大小。
最終得出
平均單次IO大小(IO Chunk Size) = avgrq-sz
平均IO響應時間(IO Response Time) = await
IOPS(IO per Second) = r/s + w/s
吞吐率(Throughtput) = rkB/s + wkB/s
iowait并不能反應磁盤瓶頸
其實際測量的是cpu時間: iowait = (cpu idle time)/(all cpu time)
高速cpu會造成很高的iowait值,但這并不代表磁盤是系統的瓶頸。唯一能說明磁盤是系統瓶頸的方法,就是很高的read/write時間,一般來說超過20ms,就代表了不太正常的磁盤性能。為什么是20ms呢?一般來說,一次讀寫就是一次尋道+一次旋轉延遲+數據傳輸的時間。由于,現代硬盤數據傳輸就是幾微秒或者幾十微秒的事情,遠遠小于尋道時間220ms和旋轉延遲48ms,所以只計算這兩個時間就差不多了,也就是15~20ms。只要大于20ms,就必須考慮是否交給磁盤讀寫的次數太多,導致磁盤性能降低了。
在Linux下,可以通過iostat命令查看磁盤性能。其中的svctm一項,反應了磁盤的負載情況,如果該項大于15ms,并且util%接近100%,那就說明,磁盤現在是整個系統性能的瓶頸了
上述理論也就是說只有磁盤表現出的讀寫能力可以說明磁盤是否有問題,如果磁盤發揮正常,如達到15ms的要求,那么如果cpu超水平發水,iowait還是會出現的。也就說iowait其實是cpu和磁盤的比賽,有一個發揮不正常都會產生iowait高的現象,但不能說磁盤的問題,也可能是cpu的問題
同時還可以安裝iotop工具,查看每個進程使用了多少IO流量
例子
vmstat下的b和wa列的值比較大,iostat下的磁盤利用率高
如果wa超過20%,說明IO等待嚴重,引起IO等待的原因可能是磁盤大量隨機讀寫造成的,也可能是磁盤或者磁盤控制器的帶寬瓶頸造成的(主要是塊操作)
bi+bo參考值為1000,如果超過1000,而且wa值較大,則表示系統磁盤IO有問題
調優
- 各個磁盤的使用率是否非常高(%util),確定是哪塊磁盤問題
- 確定應用是順序還是隨機讀取硬盤,順序要看每秒的讀寫量,隨機要看IOPS(同時計算磁盤所能承受的最大的IOPS)
- 如果磁盤慢,要比較await和svctm(等待時間、實際操作時間),如果await遠大于svctm,則應用將變慢
- 監控swap和系統分區,確保虛擬內存不是文件系統IO的瓶頸
- 更換更快的存儲設備
- 使用多個磁盤(RAID)
- 增加系統的文件緩存
- 應用級別則減少讀寫次數(使用buffered的IO、整合數據、合并讀寫)
- 選擇正確的IO調度算法:CFQ、Deadline、NOOP
- 選擇正確的文件系統:Ext2、Ext3、ReiserFS
- 選擇正確的日志模式:journal、ordered、writeback
- 選擇正確的塊大小
網絡監控與調優
- 網絡質量監控
netstat -i
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 0 20403566 0 0 0 7747807 0 0 0 BMRU
lo 16436 0 55899937 0 0 0 55899937 0 0 0 LRU
字段 | 說明 |
---|---|
Iface | 網絡設備的接口名稱 |
MTU | 最大傳輸單元,單位字節 |
RX-OK/TX-OK | 已經準確無誤的接收/發送了多少數據包 |
RX-ERR/TX-ERR | 接收/發送數據包時產生了多少錯誤 |
RX-DRP/TX-DRP | 接收/發送數據包時丟棄了多少數據包 |
RX-OVR/TX-OVR | 由于誤差而遺失了多少數據包 |
Flg | 接口標記,L:表示該接口是個回環設備,B:表示設置了廣播地址,M:表示接收所有數據包,R:表示接口正在運行,U:表示接口處于活動狀態,O:表示在該接口上禁用arp,P:表示一個點到點的連接 |
正常情況下,RX-ERR/TX-ERR、RX-DRP/TX-DRP和RX-OVR/TX-OVR的值都應該為0,如果這幾個選項的值不為0,并且很大,那么網絡質量肯定有問題,網絡傳輸性能也一定會下降
- 顯示各種連接狀態的個數
netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n
指定某個ip的
netstat -nat |grep {IP-address} | awk '{print $6}' | sort | uniq -c | sort -n
指定某個端口
netstat -nat |grep {port} | awk '{print $6}' | sort | uniq -c | sort -n
- 列出當前端口被哪個進程占用
netstat -nap | grep port
- 安裝iftop工具,查看各進程的網絡的流量
調優
- 增加網絡緩存
/proc/sys/net/ipv4/tcp_mem
/proc/sys/net/core/rmem_default
/proc/sys/net/core/rmem_max
/proc/sys/net/core/wmem_default
/proc/sys/net/core/wmem_max
/proc/sys/net/core/optmem_max - 調整窗口大小
通過讀寫緩存大小進行調整(rmem_max、wmem_max)
設定的值=網卡速率(bytes/s)*延時(sec),延時通過ping命令可得 - TCP調優
接收大量客戶端:sysctl -w net.ipv4.tcp_tw_reuse=1和sysctl -w net.ipv4.tcp_tw_recycle=1 (TIME_WAIT重用)
盡快釋放回收FIN_WAIT_2狀態的socket:sysctl -w net.ipv4.tcp_fin_timeout=30
盡快釋放回收空閑的連接:sysctl -w net.ipv4.tcp_keepalive_time=1800
增加backlog以便接收更多客戶端:sysctl -w net.ipv4.tcp_max_syn_backlog=4096
性能監控工具
性能測試工具
性能優化工具
總結
- 調優的目的是高效地使用資源,盡可能地使用最多的資源,從而提高性能
- 任何資源都要查看是資源使用率滿了,還是沒有高效使用資源
例如CPU使用率高,是因為算法問題(死循環,低效算法),還是因為程序本身就需要這么多CPU。如果CPU使用率低,則查看是因為資源等待還是線性操作。
又如I/O,wa低下,也有可能I/O的問題(當然不是硬件問題),wa低下代表磁盤的使用率低下。這時要看到底是程序本身不怎么使用磁盤,還是沒有高效使用(大量隨機操作,而不是批量操作,順序寫入,使用緩沖等) - 如果要提升服務器端的響應時間RT
采用減少IO的時間能達到最佳效果,比如合并多個IO請求
減少IO的調用次數:并發HTTP請求(無上下文依賴,多個連接,一個線程)、HTTP連接池(長連接)
減少CPU的使用時間
使用緩存 - 如果要提升QPS
采用優化CPU的時間能達到最佳效果,同時可以加大線程數
減少CPU的使用時間
增加CPU的數量
減少同步鎖
如果CPU不能被壓到85%以上,并且此時的QPS已經達到了峰值,則說明另有瓶頸