1. 概述
應用的性能極限是服務等級協議中關注的重點。找到性能極限的關鍵在於知道該監控哪些數據、監控軟件棧的哪些部分以及使用哪些工具。本篇文章將介紹需要監控的操作系統數據以及可用的操作系統性能監控攻擊,還會給出一般性指導原則。主要涉及的操作系統是Windows 7和Ubuntu 12.04.5 LTS。我們更多的是介紹哪些是需要重點監控的系統屬性以及為何要監控他們。
找到性能問題的第一步是監控應用的行為,通過監控提供的線索,可以將性能問題進行歸類。
首先要給出幾個概念的定義:性能監控,性能分析和性能調優。
性能監控:一種以非侵入方式收集或查看應用運行性能數據的活動。當應用爆出性能問題卻沒有足以定位根本原因的線索時,首先會進行性能監控,隨后是性能分析;
性能分析:一種以侵入方式收集運行性能數據的活動,它會影響應用的吞吐量或響應性;
性能調優:一種為改善應用響應性或吞吐量而更改參數,源代碼或屬性配置的活動,性能調優通常是在性能監控或性能分析之后。
2. CPU
要使應用的性能或擴展性達到最高,就必須充分利用分配給它的CPU周期。特別需要注意的是:應用消耗很多CPU並不意味着性能或擴展性達到了最高。
大多數操作的CPU使用率分為用戶態CPU使用率和系統態CPU使用率。用戶態CPU使用率是指執行應用程序代碼的時間占總CPU時間的百分比;系統態CPU使用率是指應用執行操作系統調用的時間占總CPU時間的百分比。系統態CPU使用率高意味着共享資源有競爭或IO設備之間有大量的交互。
所以在理想狀態下,應用達到最高性能和擴展性時,它的系統態CPU使用率是0%,所以提供應用性能和擴展性的一個目標是盡可能降低系統態CPU使用率。
2.1 監控CPU使用率:Windows 7
Windows上最常用的CPU使用率監控工具是Task Manager(任務管理器)和Performance Monitor(性能監控器)
2.1.1 任務管理器和性能監控器
任務管理器:
左上方CPU Usage(CPU使用率)顯示了所有處理器CPU使用率的總和;
右上方CPU使用記錄面板顯示了每個處理器CPU使用率的歷史信息,綠色線代碼用戶態和系統態CPU使用率的總和,紅色線是系統態CPU使用率,上下兩線之間的差就是用戶態CPU使用率。(必須勾選菜單“查看”->“顯示內核時間”才能顯示系統態CPU使用率)
性能監控器:右鍵計算機->管理->系統工具->性能->監控工具->性能監控器
性能監控器使用了稱為性能對象的概念,性能對象分為網絡,內存,處理器,線程,進程,網絡接口,邏輯磁盤等類別。每一類都含有特定的性能屬性或計數器,可以作為監控的性能統計數據。
右鍵性能監控器的顯示區域,在彈出菜單中選擇Add Counters(添加計數器),選擇性能對象Processor,選擇計數器%User Time和%Privileged Time在點擊Add按鈕,即可監控用戶態CPU使用率和系統態CPU使用率。注:Windows使用術語Privileged Time描述內核或系統態CPU使用率。如圖:
如下是實際的監控數值:
本實例中的User Time高於Privileged Time,這和預想的結果一致,即執行應用程序代碼的時間超過執行操作系統內核代碼的時間。
2.1.2 Windows typeperf
Windows typeperf是收集操作系統性能統計數據的命令行工具。
如果要監控User Time和Privileged Time可以使用如下命令:
typeperf "\Processor(_Total)\% User Time" "\Processor(_Total)\% Privileged Time"
輸出的第一行是表頭,描述所采集的數據。下面幾行是數據,每行的日期時間戳標示采集相應性能計數器值的時間點,默認情況下,typeperf的報告間隔是1秒,-si可以設置間隔。
2.2 監控CPU使用率:Linux
Linux提供監控CPU使用率的命令行工具,可以保留文本形式的CPU使用率運行歷史或日志。
2.2.1 vmstat
vmstat顯示所有虛擬處理器的總CPU使用率,而不能查看每個CPU的使用率。
r:運行隊列,運行隊列中輕量級進程的實際數量;
b:阻塞的進程;
swpd:虛擬內存已使用的大小,如果大於0,標示你的物理內存不足;
free:空閑的物理內存;
buff:linux系統用來存儲目錄里面有什么內容,權限等的緩存;
cache:直接用來記憶我們打開的文件,給文件做緩存(把空閑的物理內存的一部分用作文件和目錄的緩存,是為了提供程序執行的性能,當程序使用內存時,buffer/cached會很快被使用);
si:每秒從磁盤讀入虛擬內存的大小,如果這個值大於0,標示物理內存不夠用或內存泄漏;
so:每秒虛擬內存寫入磁盤的大小,如果這個值大於0,同上;
bi:塊設備每秒接收的快數量;
bo:塊設備每秒阿松的快數量,例如讀取文件,bo就要大於0,。bi和bo一般都要接近0,不然就是IO過於頻繁;
in:每秒CPU中斷次數,包括時間中斷;
cs:每秒上下文切換次數;
us:用戶態CPU使用率;
sy:系統態CPU使用率,如果太高,標示系統調用時間長,例如是IO操作頻繁;
id:空閑率或CPU可用率。us,sy的和應該等於100減去id,即100-id的值;
wa:等待IO CPU時間;
2.2.2 mpstat
mpstat是Multiprocessor Statistics的縮寫,是實時系統監控工具。其不但能查看所有CPU的平均狀況信息,而且能夠查看特定CPU的信息。
語法:
mpstat [-P { |ALL}] [internal [count]]
-P {|ALL}表示監控哪個CPU,CPU在[0, CPU個數-1]中取值;
internal相鄰的兩次采樣的間隔時間;
count采樣的次數;
實例:
mpstat -P ALL 2分別顯示所有和每個CPU的信息;
mpstat -P 0 2 3:顯示CPU0的信息,mpstat 2 3:顯示所有CPU的平均信息:
在internal時間段里,各個字段的意義:
user:用戶態的CPU時間(%)
nice: 負進程的CPU時間(%)
sys:內核時間(%)
iowait:硬盤IO等待時間(%)
irq:硬中斷時間(%)
soft:軟中斷時間(%)
idle:CPU除去等待磁盤IO操作外的因為任何原因而空閑的時間閑置時間(%)
2.2.3 top
top命令不僅包括CPU使用率也包括進程統計數據和內存使用率。
輸出主要包括兩部分:上半部分是整個系統的統計信息,下半部分是進程的統計信息(默認安裝CPU使用率由高到低排序)
top是從進程上了解CPU使用率概況的好工具, top -p pid可以查看具體進程的CPU和內存使用率。
第1行 | 15:13:19 當前系統時間 xx 系統已經運行了多長時間 x users 當前有x個用戶登錄系統 load avage:,, 分別表示1分鍾,5分鍾,15分鍾的負載情況;如果這個數值除以邏輯CPU的數量,結果大於5表明系統在超負荷運行 |
第2行 | Tasks:系統現在共有x個進程,其中處於運行中的有x個,x個在休眠(sleep),stopped狀態的有x個,zombie僵屍狀態的有x個。 |
第3行 | us:用戶空間占用CPU的百分比;sy:內核空間占用的CPU百分比;ni:改變過優先級的進程占用CPU的百分比 wa:IO等待占用CPU的百分比;hi:硬中斷占用百分比,si:軟中斷占用百分比 |
第4行 | total:物理內存總量,used:使用中的內存重量,free:空閑內存總量,buffers:緩存的內存量 used指的是現在系統內核控制的內存數,free是內核還未納入其掛你控制范圍的數量。 納入內核管理的內存不見得都在使用中,還包括過去使用過的現在可以被重復利用的內存, 內核並不把這些可被重新使用的內存交歡給free,因此linux上free內存少的時候,也不一定就是其實內存占用多。 有個近似的計算公式可以計算內存的使用量 = 第4行的free + 第4行的buffers + 第5行的cached |
第5行 | total:交換區總量,used:使用的交換區總量,free:空閑交換區總量,cached:緩沖的交換區總量; 在top中要時刻監控swap交換分區的used,如果這個數值不斷變化,說明內核在不斷進行內存和swap的數據交換,這是真正的內存不夠用了。 |
第6行 | 空行 |
第7行 | PID進程ID;USER進程所有者;PR進程優先級,NI負值標示高優先級,正直標示低優先級;VIRT進程使用的虛擬內存總量 RES進程使用的,未被換出的物理內存大小;SHR共享內存大小;S進程狀態;%CPU刪詞更新到現在的CPU時間占用百分比 %MEM進程使用的物理內存百分比;TIME+進程使用的CPU時間總計;COMMAND進程名稱。 |
3. 內存
除了CPU使用率,還需要監控系統內存相關的屬性,例如頁面調度或頁面交換,加鎖,線程遷移中的讓步式和搶占式上下文切換。系統在進行頁面交換或使用虛擬內存時,Java應用或JVM會表現出明顯的性能問題,當應用運行所需的內存超過可用物理內存時,就會發生頁面交換。為了應對這種可能出現的情況,通常腰圍系統配置swap空間。swap空間一般會在一個獨立的磁盤分區上。當應用耗盡物理內存時,操作系統會將應用的一部分置換到磁盤上的swap空間,通常是應用中最少運行的部分,以免影響整個應用或應用最忙的部分。當訪問應用中被置換出去的部分時,就必須將它從磁盤置換進內存,而這種磚活動會對應用的響應性和吞吐量造成很大影響。
此外,JVM垃圾收集器在系統頁面交換時的性能也很差,這是由於垃圾收集器為了回收不可達對象所占用的空間,需要訪問大量的內存。如果Java堆的一部分被置換出去,就必須先置換進內存以便垃圾收集器掃描存活對象,這會增加垃圾收集的持續時間。垃圾收集時一種STW操作,即停止所有正在運行的應用線程,如果此時系統正在進行頁面交換,則會引起JVM長時間的停頓,如果發現垃圾收集時間變長,系統有可能正在進行頁面交換。
3.1 監控內存利用率:Windows 7
在性能監控器中監控每秒內存頁面調度(\Memory\Pages/Second),可用內存字節數(\Memory\Available MBytes)。當可用內存變少,而且頁面調度時,系統可能正在就行頁面交換。
此外顯示Windows頁面交換的最簡單方法是typeperf命令:
第一列時間戳,第二列可用內存,第三列是每秒的頁面調度;
通過任務管理器可以看到大致可用的內存:
3.2 監控內存利用率:Linux
linux可以用vmstat輸出中的free列監控可用內存,si和so分別表示內存頁面換入和換出的量。
4. 網絡IO
分布式Java應用的性能和擴展性受限於網絡帶寬或網絡IO的性能。
4.1 監控網絡IO使用率:Linux
Linux沒有很好的網絡工具來判斷網絡使用率。
4.2 監控網絡IO使用率:Windows 7
Windows上監控網絡使用率,不能直接通過性能監控器添加性能計數器來獲得。
所以,需要知道被監控網絡接口的帶寬(指在單位時間(一般指的是1秒鍾)內能傳輸的數據量,是一個理論最高值),以及網絡接口傳輸的數據量(1秒內);
然后,利用公式計算網絡IO利用率: 利用率 = 網絡接口傳輸的數據量[1秒] / 帶寬
可以從性能監控器監控:(1)Network Interface(*)\Bytes Total/sec獲得網絡接口傳輸的數據量(2)\Network Interface(*)\Current Bandwidth獲取網絡接口帶寬
也可以通過任務管理器,直接查看網絡使用率,如圖:
Java網絡編碼建議:
單次讀寫數據量小而網絡讀寫量大的應用會消耗大量的系統態CPU,產生大量的系統調用。對於這類應用,減少系統態CPU的策略是減少網絡讀寫的系統調用;
使用非阻塞的Java NIO,而不是阻塞的java.net.Socket;
減少處理請求和發送響應的線程數,也可以改善應用性能;
從非阻塞socket中讀取數據的策略是,應用在每次讀請求時盡可能地讀取數據,當往socket中寫數據時,每個寫調用應該盡可能多寫入。
5. 磁盤IO
對於有磁盤操作的應用來說,查找性能問題,就應該監控磁盤IO。磁盤IO使用率是理解應用磁盤使用情況最有用的監控數據。
5.1 監控磁盤IO使用率:windows
性能監控器性能對象LogicalDisk有一些性能計數器可用來監控磁盤使用率,如圖:
5.2 監控磁盤IO使用率:Linux
Linux可以用iostat來監控系統的磁盤使用率和系統態CPU使用率。
rrqm:每秒進行merge的讀操作數目;wrqm:每秒進行merge的寫操作數目;
r/s:每秒完成的讀IO設備次數;w/s:每秒完成的寫IO設備次數;
rsec/s:每秒讀扇區數;wsec/s:,每秒寫扇區數;
rkB/s:每秒讀k字節數;wkB/s:秒寫k字節數;
avgrg-sz:平均每次設備IO操作的數據大小;avgqu-sz:平均IO隊列長度;
await:平均每次設備IO操作的等待時間;
svctm:平均每次設備IO操作的服務時間;
%util:每秒中有百分之幾的時間用於IO操作,即被IO消耗的CPU百分比。
如果%util接近100%說明產生的IO請求太多,IO系統已經滿負荷,磁盤可能存在瓶頸。如果svctm比較接近await,說明IO幾乎沒有等待時間;如果await遠大於svctm說明IO隊列太長,IO響應太慢,則需要進行必要優化。如果asgqu-sz比較大,也標示IO在等待。