<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          流弊666,Java應(yīng)用之性能測試瓶頸調(diào)優(yōu)

          共 14067字,需瀏覽 29分鐘

           ·

          2021-09-06 12:14

          點擊上方藍色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達

          引言:性能瓶頸調(diào)優(yōu)

          在實際的性能測試中,會遇到各種各樣的問題,比如 TPS 壓不上去等,導(dǎo)致這種現(xiàn)象的原因有很多,測試人員應(yīng)配合開發(fā)人員進行分析,盡快找出瓶頸所在。
          理想的性能測試指標(biāo)結(jié)果可能不是很高,但一定是平緩的。

          性能調(diào)優(yōu)步驟

          1. 確定問題:根據(jù)性能監(jiān)控的數(shù)據(jù)和性能分析的結(jié)果,確定性能存在的問題。
          2. 確定原因:確定問題之后,對問題進行分析,找出問題的原因。
          3. 確定解決方案(改服務(wù)器參數(shù)配置/增加硬件資源配置/修改代碼)。
          4. 驗證解決方案,分析調(diào)優(yōu)結(jié)果。
          注意:性能測試調(diào)優(yōu)并不是一次完成的過程,針對同一個性能問題,上述步驟可能要經(jīng)過多次循環(huán)才能最終完成性能調(diào)優(yōu)的目標(biāo),即:測試發(fā)現(xiàn)問題 -> 找原因 -> 調(diào)整 -> 驗證 -> 分析 -> 再測試 ...

          性能瓶頸概率分布

          60%:數(shù)據(jù)庫瓶頸
          • 數(shù)據(jù)庫服務(wù)器 CPU 使用率高(慢查詢、SQL 過多、連接數(shù)過多)
          • 拋出連接數(shù)過多(連接池設(shè)置太小,導(dǎo)致連接排隊)
          • 數(shù)據(jù)庫出現(xiàn)死鎖
          25%:應(yīng)用瓶頸
          • 應(yīng)用出現(xiàn)內(nèi)存泄露
          • 應(yīng)用出現(xiàn)線程競爭/死鎖
          • 程序代碼的算法復(fù)雜度
          • 中間件、第三方應(yīng)用出現(xiàn)異常
          • 計算密集型任務(wù)引起 CPU 負載高
          • I/O 密集型任務(wù)引起 I/O 負載高
          10%:壓測工具瓶頸
          • JMeter 單機負載能力有限,如果需要模擬的用戶請求數(shù)超過其負載極限,也會導(dǎo)致 TPS 壓不上去
          5%:Linux 機器出現(xiàn)異常
          • Linux 可用內(nèi)存無法回收(開銷速率大于回收速率)

          系統(tǒng)資源

          • CPU
            • 監(jiān)控內(nèi)容:CPU 使用率、CPU 使用類型(用戶進程、內(nèi)核進程)
            • 瓶頸分析:CPU已壓滿(接近 100%),需要再看其他指標(biāo)的拐點所出現(xiàn)的時刻是否與 CPU 壓滿的時刻基本一致。
          • 內(nèi)存
            • 監(jiān)控內(nèi)容:實際內(nèi)存、虛擬內(nèi)存
            • 瓶頸分析:內(nèi)存不足時,操作系統(tǒng)會使用虛擬內(nèi)存,從虛擬內(nèi)存讀取數(shù)據(jù),影響處理速度。
          • 磁盤 I/O
            • 監(jiān)控內(nèi)容:I/O 速度、磁盤等待隊列
            • 瓶頸分析:磁盤 I/O 成為瓶頸時,會出現(xiàn)磁盤I/O繁忙,導(dǎo)致交易執(zhí)行時在 I/O 處等待。
          • 網(wǎng)絡(luò)
            • 監(jiān)控內(nèi)容:網(wǎng)絡(luò)流量(帶寬使用率)、網(wǎng)絡(luò)連接狀態(tài)
            • 瓶頸分析:如果接口傳遞的數(shù)據(jù)包過大,超過了帶寬的傳輸能力,就會造成網(wǎng)絡(luò)資源競爭, 導(dǎo)致 TPS 上不去。

          發(fā)現(xiàn)了瓶頸后,只要對癥下藥就可以了。簡單來說無論哪個地方出現(xiàn)瓶頸,只需要降低壓力或者增加這部分瓶頸資源(應(yīng)用軟件沒有瓶頸或優(yōu)化空間之后),即可緩解癥狀。
          • CPU 瓶頸:增加 CPU 資源。
          • 內(nèi)存瓶頸:增加內(nèi)存、釋放緩存。
          • 磁盤 I/O 瓶頸:更換性能更高的磁盤(如固態(tài) SSD)。
          • 網(wǎng)絡(luò)帶寬瓶頸;增加網(wǎng)絡(luò)帶寬。

          CPU

          后臺服務(wù)的所有指令和數(shù)據(jù)處理都是由 CPU 負責(zé),服務(wù)對 CPU 的利用率對服務(wù)的性能起著決定性的作用。

          top 參數(shù)詳解

          下面以 top 命令的輸出例,對 CPU 各項主要指標(biāo)進行說明:
          • us(user):運行(未調(diào)整優(yōu)先級的)用戶進程所消耗的 CPU 時間的百分比。
            • 像 shell 程序、各種語言的編譯器、數(shù)據(jù)庫應(yīng)用、web 服務(wù)器和各種桌面應(yīng)用都算是運行在用戶地址空間的進程。
            • 這些程序如果不是處于 idle 狀態(tài),那么絕大多數(shù)的 CPU 時間都是運行在用戶態(tài)。
          • sy(system):運行內(nèi)核進程所消耗的 CPU 時間的百分比。
            • 所有進程要使用的系統(tǒng)資源都是由 Linux 內(nèi)核處理的。當(dāng)處于用戶態(tài)(用戶地址空間)的進程需要使用系統(tǒng)的資源時,比如需要分配一些內(nèi)存、或是執(zhí)行 I/O 操作、再或者是去創(chuàng)建一個子進程,此時就會進入內(nèi)核態(tài)(內(nèi)核地址空間)運行。事實上,決定進程在下一時刻是否會被運行的進程調(diào)度程序就運行在內(nèi)核態(tài)。
            • 對于操作系統(tǒng)的設(shè)計來說,消耗在內(nèi)核態(tài)的時間應(yīng)該是越少越好。通常 sy 比例過高意味著被測服務(wù)在用戶態(tài)和系統(tǒng)態(tài)之間切換比較頻繁,此時系統(tǒng)整體性能會有一定下降。
            • 在實踐中有一類典型的情況會使 sy 變大,那就是大量的 I/O 操作,因此在調(diào)查 I/O 相關(guān)的問題時需要著重關(guān)注它。
            • 大部分后臺服務(wù)使用的 CPU 時間片中 us 和 sy 的占用比例是最高的。同時這兩個指標(biāo)又是互相影響的,us 的比例高了,sy 的比例就低,反之亦然。
            • 另外,在使用多核 CPU 的服務(wù)器上,CPU 0 負責(zé) CPU 各核間的調(diào)度,CPU 0 上的使用率過高會導(dǎo)致其他 CPU 核心之間的調(diào)度效率變低。因此測試過程中需要重點關(guān)注 CPU 0。
          • ni(niced):用做 nice 加權(quán)的進程分配的用戶態(tài) CPU 時間百分比。
            • 每個 Linux 進程都有個優(yōu)先級,優(yōu)先級高的進程有優(yōu)先執(zhí)行的權(quán)利,這個叫做 pri。進程除了優(yōu)先級外,還有個優(yōu)先級的修正值。這個修正值就叫做進程的 nice 值。
            • 這里顯示的 ni 表示調(diào)整過 nice 值的進程消耗掉的 CPU 時間。如果系統(tǒng)中沒有進程被調(diào)整過 nice 值,那么 ni 就顯示為 0。
            • 一般來說,被測服務(wù)和服務(wù)器整體的 ni 值不會很高。如果測試過程中 ni 的值比較高,需要從服務(wù)器 Linux 系統(tǒng)配置、被測服務(wù)運行參數(shù)查找原因。
          • id(idle):空閑的 CPU 時間百分比。
            • 一般情況下, us + ni + id 應(yīng)該接近 100%。
            • 線上服務(wù)運行過程中,需要保留一定的 id 冗余來應(yīng)對突發(fā)的流量激增。
            • 在性能測試過程中,如果 id 一直很低,吞吐量上不去,需要檢查被測服務(wù)線程/進程配置、服務(wù)器系統(tǒng)配置等。
          • wa(I/O wait):CPU 等待 I/O 完成時間百分比。
            • 和 CPU 的處理速度相比,磁盤 I/O 操作是非常慢的。有很多這樣的操作,比如:CPU 在啟動一個磁盤讀寫操作后,需要等待磁盤讀寫操作的結(jié)果。在磁盤讀寫操作完成前,CPU 只能處于空閑狀態(tài)。
            • Linux 系統(tǒng)在計算系統(tǒng)平均負載時會把 CPU 等待 I/O 操作的時間也計算進去,所以在我們看到系統(tǒng)平均負載過高時,可以通過 wa 來判斷系統(tǒng)的性能瓶頸是不是過多的 I/O 操作造成的。
            • 磁盤、網(wǎng)絡(luò)等 I/O 操作會導(dǎo)致 CPU 的 wa 指標(biāo)提高。通常情況下,網(wǎng)絡(luò) I/O 占用的 wa 資源不會很高,而頻繁的磁盤讀寫會導(dǎo)致 wa 激增。
            • 如果被測服務(wù)不是 I/O 密集型的服務(wù),那需要檢查被測服務(wù)的日志量、數(shù)據(jù)載入頻率等。
            • 如果 wa 高于 10% 則系統(tǒng)開始出現(xiàn)卡頓;若高于 20% 則系統(tǒng)幾乎動不了;若高于 50% 則很可能磁盤出現(xiàn)故障。
          • hi:硬中斷消耗時間百分比。
          • si:軟中斷消耗時間百分比。
            • 硬中斷是外設(shè)對 CPU 的中斷,即外圍硬件發(fā)給 CPU 或者內(nèi)存的異步信號就是硬中斷信號;軟中斷由軟件本身發(fā)給操作系統(tǒng)內(nèi)核的中斷信號。
            • 通常是由硬中斷處理程序或進程調(diào)度程序?qū)Σ僮飨到y(tǒng)內(nèi)核的中斷,也就是我們常說的系統(tǒng)調(diào)用(System Call)。
            • 在性能測試過程中,hi 會有一定的 CPU 占用率,但不會太高。對于 I/O 密集型的服務(wù),si 的 CPU 占用率會高一些。
          • st:虛擬機等待 CPU 資源的時間。
            • 只有 Linux 在作為虛擬機運行時 st 才是有意義的。它表示虛機等待 CPU 資源的時間(虛機分到的是虛擬 CPU,當(dāng)需要真實的 CPU 時,可能真實的 CPU 正在運行其它虛機的任務(wù),所以需要等待)。

          性能分析思路

          • wa(IO wait)的值過高,表示硬盤存在 I/O 瓶頸。
          • id(idle)值高,表示 CPU 較空閑。
          • 如果 id 值高但系統(tǒng)響應(yīng)慢時,有可能是 CPU 等待分配內(nèi)存,此時應(yīng)加大內(nèi)存容量。
          • 如果 id 值持續(xù)低于 10,那么系統(tǒng)的 CPU 處理能力相對較低,表明系統(tǒng)中最需要解決的資源是 CPU。

          案例分析

          現(xiàn)象:CPU 的 us 和 sy 不高,但 wa 很高。
          如果被測服務(wù)是磁盤 I/O 密集型服務(wù),wa 高屬于正?,F(xiàn)象。但如果不是此類服務(wù),最可能導(dǎo)致 wa 高的原因有兩個:
          • 服務(wù)對磁盤讀寫的業(yè)務(wù)邏輯有問題,讀寫頻率過高,寫入數(shù)據(jù)量過大,如不合理的數(shù)據(jù)載入策略、log 過多等,都有可能導(dǎo)致這種問題。
          • 服務(wù)器內(nèi)存不足,服務(wù)在 swap 分區(qū)不停的換入換出。

          LOAD

          Linux 的系統(tǒng)負載指在特定時間間隔內(nèi)(一個 CPU 周期)運行隊列中的平均進程數(shù)。
          (注意:Linux 中的 Load 體現(xiàn)的是整體系統(tǒng)負載,即 CPU 負載 + 磁盤負載 + 網(wǎng)絡(luò)負載 + 其余外設(shè)負載,并不能完全等同于 CPU 使用率。而在其余系統(tǒng)如 Unix,Load 還是只代表 CPU 復(fù)雜。)
          從服務(wù)器負載的定義可以看出,服務(wù)器運行最理想的狀態(tài)是所有 CPU 核心的運行隊列都為 1,即所有活動進程都在運行,沒有等待。這種狀態(tài)下服務(wù)器運行在負載閾值下。
          通常情況下,按照經(jīng)驗值,服務(wù)器的負載應(yīng)位于閾值的 70%~80%,這樣既能利用服務(wù)器大部分性能,又留有一定的性能冗余應(yīng)對流量增長。
          查看系統(tǒng)負載閾值的命令如下:

          Linux 提供了很多查看系統(tǒng)負載的命令,最常用的是 top 和 uptime。
          top 和 uptime 針對負載的輸出內(nèi)容相同,都是系統(tǒng)最近 1 分鐘、5 分鐘、15 分鐘的負載均值:
          這三個數(shù)值的使用方法和 CPU 核數(shù)相關(guān),首先確認 CPU 物理總核數(shù):
          • /proc/cpuinfo 中的 processors 的最大值不一定是 CPU 的核數(shù),有可能該 CPU 支持超線程技術(shù),從而 processors 是物理核數(shù)的 2 倍。
          • 這里我們需要準(zhǔn)確的核數(shù),具體方法為:找到 /proc/cpuinfo 文件中所有的 physical id 后的數(shù)值,取得最大的數(shù)值,加一后就是實際的 CPU 個數(shù)。然后查找任意一個 processors 下的 cpu cores,即是該顆 CPU 的核數(shù),實際 CPU 個數(shù)乘以核數(shù)即為 CPU 的物理總核數(shù)。
          示例:
          [root@localhost home]# cat /proc/cpuinfo |grep "physical id"
          physical id     : 0
          physical id     : 0
          [root@localhost home]# cat /proc/cpuinfo |grep "cpu cores"
          cpu cores       : 2
          cpu cores       : 2
          物理 CPU 個數(shù)為 0+1=1 個,每個 CPU 的核數(shù)為 2 個,所以總的物理核數(shù)為 2x1=2。
          計算結(jié)果說明該機器的在單位時間內(nèi)可以處理的進程數(shù)是 2 個,如果單位時間內(nèi)進程數(shù)超過 2 個,就會出現(xiàn)擁堵的情況,load 就會持續(xù)增高,增高到一定程度,就會出現(xiàn)系統(tǒng)崩潰等異常情況。

          在性能測試過程中,系統(tǒng)負載是評價整個系統(tǒng)運行狀況最重要的指標(biāo)之一。通常情況下:
          • 負載測試時:系統(tǒng)負載應(yīng)接近但不能超過閾值。
          • 并發(fā)測試時:系統(tǒng)負載最高不能超過閾值的 80%。
          • 穩(wěn)定性測試時:系統(tǒng)負載應(yīng)在閾值的 50% 左右。

          機器針對突發(fā)情況的處理
          • 如果 1 分鐘 load 很高,5 分鐘 load 較高,15 分鐘 load 起伏不大的情況下,說明該次高 load 為突發(fā)情況,可以容忍。
          • 如果高 load 持續(xù),導(dǎo)致 5 分鐘和 15 分鐘 load 都已經(jīng)超過報警值,這時候需要考慮進行處理。
          • 如果 15 分鐘 load 高于 1 分鐘 load,說明高 load 情況已經(jīng)得到緩解。

          內(nèi)存

          性能測試過程中對內(nèi)存監(jiān)控的主要目的是檢查被測服務(wù)所占用內(nèi)存的波動情況。

          top 參數(shù)詳解

          在 Linux 系統(tǒng)中有多個命令可以獲取指定進程的內(nèi)存使用情況,最常用的是 top 命令,如下圖所示:
          • VIRT:進程所使用的虛擬內(nèi)存的總數(shù)。它包括所有的代碼,數(shù)據(jù)和共享庫,加上已換出的頁面,所有已申請的總內(nèi)存空間。
          • RES:進程正在使用的沒有交換的物理內(nèi)存(棧、堆)。申請內(nèi)存后該內(nèi)存段已被重新賦值。
          • SHR:進程使用共享內(nèi)存的總數(shù)。該數(shù)值只是反映可能與其它進程共享的內(nèi)存,不代表這段內(nèi)存當(dāng)前正被其他進程使用。
          • SWAP:進程使用的虛擬內(nèi)存中被換出的大小。交換的是已經(jīng)申請但沒有使用的空間(包括棧、堆、共享內(nèi)存)。
          • DATA:進程除可執(zhí)行代碼以外的物理內(nèi)存總量,即進程棧、堆申請的總空間。
          從上面的解釋可以看出,測試過程中主要監(jiān)控 RES 和 VIRT。對于使用了共享內(nèi)存的多進程架構(gòu)服務(wù),還需要監(jiān)控 SHR。

          free 參數(shù)詳解

          free 命令顯示系統(tǒng)內(nèi)存的使用情況,包括物理內(nèi)存、交換內(nèi)存(swap)和內(nèi)核緩沖區(qū)內(nèi)存。如果加上 -h 選項(控制顯示單位),輸出的結(jié)果會友好很多:
          有時我們需要持續(xù)的觀察內(nèi)存的狀況,此時可以使用 -s 選項并指定間隔的秒數(shù):如 free -h -s 3 表示每隔 3 秒輸出一次內(nèi)存的使用情況,直到按下 ctrl + c。
          • Mem 行:物理內(nèi)存的使用情況。
          • Swap 行:交換空間的使用情況。
            • swap space 是磁盤上的一塊區(qū)域,可以是一個分區(qū),也可以是一個文件,所以具體的實現(xiàn)可以是 swap 分區(qū)也可以是 swap 文件。當(dāng)系統(tǒng)物理內(nèi)存吃緊時,Linux 會將內(nèi)存中不常訪問的數(shù)據(jù)保存到 swap 上,這樣系統(tǒng)就有更多的物理內(nèi)存為各個進程服務(wù),而當(dāng)系統(tǒng)需要訪問 swap 上存儲的內(nèi)容時,再將 swap 上的數(shù)據(jù)加載到內(nèi)存中,這就是常說的換出和換入。
            • 交換空間可以在一定程度上緩解內(nèi)存不足的情況,但是它需要讀寫磁盤數(shù)據(jù),所以性能不是很高。因此當(dāng)交換空間內(nèi)存開始使用,則表明內(nèi)存嚴(yán)重不足。
            • 如果系統(tǒng)內(nèi)存充足或是做性能壓測的機器,可以使用 swapoff -a 關(guān)閉交換空間,或在 /etc/sysctl.conf 文件中設(shè)置 swappiness 值。如果系統(tǒng)內(nèi)存不富余,則需要根據(jù)物理內(nèi)存的大小來設(shè)置交換空間的大小,具體的策略網(wǎng)上有很豐富的資料。
          • total 列:系統(tǒng)總的可用物理內(nèi)存和交換空間大小。
          • used 列:已經(jīng)被使用的物理內(nèi)存和交換空間大小。
          • free 列:還有多少物理內(nèi)存和交換空間可用使用(真正尚未被使用的物理內(nèi)存數(shù)量)
            • 在吞吐量固定的前提下,如果內(nèi)存持續(xù)上漲,那么很有可能是被測服務(wù)存在明顯的內(nèi)存泄漏,需要使用 valgrind 等內(nèi)存檢查工具進行定位。
          • shared 列:被共享使用的物理內(nèi)存大小。
          • buffer/cache 列:被 buffer 和 cache 使用了的物理內(nèi)存大小。
            • Linux 內(nèi)核為了提升磁盤操作的性能,會消耗一部分空閑內(nèi)存去緩存磁盤數(shù)據(jù),就是 buffer 和 cache。
            • 如果給所有應(yīng)用分配足夠內(nèi)存后,物理內(nèi)存還有剩余,linux 會盡量再利用這些空閑內(nèi)存,以提高整體 I/O 效率,其方法是把這部分剩余內(nèi)存再劃分為 cache 及 buffer 兩部分加以利用。
            • 所以,空閑物理內(nèi)存不多,不一定表示系統(tǒng)運行狀態(tài)很差,因為內(nèi)存的 cache 及 buffer 部分可以隨時被重用,在某種意義上,這兩部分內(nèi)存也可以看作是額外的空閑內(nèi)存。
          • available 列:還可以被應(yīng)用程序使用的物理內(nèi)存大小。
            • 從應(yīng)用程序的角度來說,available = free + buffer + cache。請注意,這只是一個很理想的計算方式,實際中的數(shù)據(jù)往往有較大的誤差。

          釋放緩存內(nèi)存
          方式一:手動釋放緩存內(nèi)存
          snyc
          echo 3 > /proc/sys/vm/drop_caches
          free -m
          方式二:修改 linux 配置自動釋放
          /proc/sys/vm/drop_caches 這個值的 0 改為 1

          磁盤 I/O

          性能測試過程中,如果被測服務(wù)對磁盤讀寫過于頻繁,會導(dǎo)致大量請求處于 I/O 等待的狀態(tài),系統(tǒng)負載升高,響應(yīng)時間變長,吞吐量下降。
          iostat 參數(shù)詳解
          Linux 下可以用 iostat 命令來監(jiān)控磁盤狀態(tài)。
          iostat -d 2 10 表示每 2 秒統(tǒng)計一次基礎(chǔ)數(shù)據(jù),統(tǒng)計 10 次:
          • tps:該設(shè)備每秒的傳輸次數(shù)?!耙淮蝹鬏敗币馑际恰耙淮?I/O 請求”。多個邏輯請求可能會被合并為“一次 I/O 請求”?!耙淮蝹鬏敗闭埱蟮拇笮∈俏粗?。
          • kB_read/s:每秒從設(shè)備(driveexpressed)讀取的數(shù)據(jù)量,單位為 Kilobytes。
          • kB_wrtn/s:每秒向設(shè)備(driveexpressed)寫入的數(shù)據(jù)量,單位為 Kilobytes。
          • kB_read:讀取的總數(shù)據(jù)量,單位為 Kilobytes。
          • kB_wrtn:寫入的總數(shù)量數(shù)據(jù)量,單位為 Kilobytes。
          從 iostat -d 的輸出中,能夠獲得系統(tǒng)運行最基本的統(tǒng)計數(shù)據(jù)。但對于性能測試來說,這些數(shù)據(jù)不能提供更多的信息。需要加上 -x 參數(shù)。
          iostat -x 參數(shù)詳解
          如 iostat -x 2 10 表示每 2 秒統(tǒng)計一次更詳細數(shù)據(jù),統(tǒng)計 10 次:
          • rrqm/s:每秒這個設(shè)備相關(guān)的讀取請求有多少被 Merge 了。
            • 當(dāng)系統(tǒng)調(diào)用需要讀取數(shù)據(jù)的時候,VFS 將請求發(fā)到各個 FS,如果 FS 發(fā)現(xiàn)不同的讀取請求讀取的是相同 Block 的數(shù)據(jù),F(xiàn)S 會將這個請求合并 Merge。
          • wrqm/s:每秒這個設(shè)備相關(guān)的寫入請求有多少被 Merge 了。
          • await:每一個 I/O 請求的處理的平均時間(單位:毫秒)。
            • await 的大小一般取決于服務(wù)時間(svtcm)以及 I/O 隊列的長度和 I/O 請求的發(fā)出模式。假設(shè) svtcm 比較接近 await,說明 I/O 差點沒有等待時間。
            • 假設(shè) await 遠大于 svctm(如大于 5),就要考慮 I/O 有壓力瓶頸,說明 I/O 隊列太長,應(yīng)用得到的響應(yīng)時間變慢。假設(shè)響應(yīng)時間超過了用戶能夠容許的范圍,這時可以考慮更換更快的磁盤。
          • svctm:I/O 平均服務(wù)時間。
          • %util:在統(tǒng)計時間內(nèi)有百分之多少用于 I/O 操作。
            • 例如,如果統(tǒng)計間隔 1 秒,該設(shè)備有 0.8 秒在處理 I/O,而 0.2 秒閑置,那么該設(shè)備的 %util = 0.8/1 = 80%,該參數(shù)暗示了設(shè)備的繁忙程度。
            • %util 接近100% 表明 I/O 請求太多,I/O 系統(tǒng)繁忙,磁盤可能存在瓶頸。
          iostat -x 完整參數(shù)如下:

          - rrqm/s: 每秒進行 merge 的讀操作數(shù)目。即 delta(rerge)/s
          - wrqm/s: 每秒進行 merge 的寫操作數(shù)目。即 delta(wmerge)/s
          - t/s: 每秒完成的讀 I/O 設(shè)備次數(shù)。即 delta(rioVs
          - w/s: 每秒完成的寫 1/O 設(shè)備次數(shù)。即 delta(wio)/s
          - rsec/s: 每秒讀扇區(qū)數(shù)。即 delta(rsect)/s
          - ws0c/s: 每秒寫扇區(qū)數(shù)。即 deita(wsect)/s
          - rkB/s: 每秒讀 K 字節(jié)數(shù)。是 rsect/s 的一半,因為每扇區(qū)大小為 512 字節(jié)。(需要計算) 
          - wkB/s: 每秒寫 K 字節(jié)數(shù)。是 wsect/s 的一半。(需要計算) 
          - avgrq+sz: 平均每次設(shè)備 I/O 操作的數(shù)據(jù)大?。ㄉ葏^(qū))。delta(rsect+wsect)/delta(rio+wio) 
          - avgqu-sz: 平均I/O隊列長度,即delta(avea)/s/1000(因為 aveq 的單位為毫秒)。 
          - await: 平均每次設(shè)備 I/O 操作的等待時間(毫秒)。即 delta(ruse+wuse)/delta(rio+wio) 
          - svctm: 平均每次設(shè)備 I/O 操作的服務(wù)時間(毫秒)。即 delta(use)/delta(rio+wio) 
          - %util:一秒中有百分之多少的時間用于 I/O 操作,或者說一秒中有多少時間 I/O 隊列是非空的。即 delta(use)/s/1000(因為 use 的單位為毫秒)

          網(wǎng)絡(luò)

          性能測試中網(wǎng)絡(luò)監(jiān)控主要包括網(wǎng)絡(luò)流量、網(wǎng)絡(luò)連接狀態(tài)的監(jiān)控。

          網(wǎng)絡(luò)流量監(jiān)控

          方法很多,網(wǎng)上有很多 shell 腳本。也可以使用 nethogs 命令。該命令與 top 類似,是一個實時交互的命令,運行界面如下:
          在后臺服務(wù)性能測試中,對于返回文本結(jié)果的服務(wù),并不需要太多關(guān)注在流量方面。

          理解帶寬
          針對一些特定的應(yīng)用,比如直播或網(wǎng)盤(文件上傳下載),帶寬瓶頸也是一個出現(xiàn)頻率較高的場景。
          服務(wù)端的帶寬分為上行(out)和下行(in)帶寬(分別對應(yīng)客戶端的下載和上傳)。
          • 看視頻看新聞使用帶寬:客戶端的下載、服務(wù)端的上行帶寬。
          • 服務(wù)端接收客戶端的數(shù)據(jù)使用帶寬:客戶端的上傳、服務(wù)端的下行帶寬。
          一個 Web 服務(wù)器如各類新聞網(wǎng)站通常需要更多的服務(wù)端上行(out)帶寬;而郵件服務(wù)器、網(wǎng)盤服務(wù)器等則通常需要更多的服務(wù)端下行帶寬(in)。
          理解帶寬速率公式
          • 1 Mb/s 帶寬速度為 128 KB/s(1024Kb / 8KB)
          • 100 Mb/s 帶寬速度為 12.5 Mb/s(考慮網(wǎng)絡(luò)損耗通常按 10M/s 或 1280KB/s 算)
          示例:5000 萬像素手機拍一張照片,照片大小約 20MB,在下述帶寬下需要耗時:
          • 10M 帶寬約 20 秒:耗時 = 流量 / 速率 = 20MB / (10Mb/8) = 20 / 1.25 = 16 秒(按 1MB/s=128KB/s 速度算即 20 秒)
          • 100M 帶寬約 2 秒:耗時 = 流量 / 速率 = 20MB / (100Mb/8) = 20 / 12.5 = 1.6 秒(按 10MB/s=128KB/s 速度算即 2 秒)
          • 1000M 帶寬約 0.2 秒:耗時 = 流量 / 速率 = 20MB / (1000Mb/8) = 20 / 125 = 0.16 秒(按 100MB/s=128KB/s 速度算即 0.2 秒)

          案例分析
          現(xiàn)象:從監(jiān)控圖表可以看出,當(dāng)前的網(wǎng)絡(luò)流量已經(jīng)基本將網(wǎng)絡(luò)帶寬占滿,因此網(wǎng)絡(luò)存在瓶頸。
          解決方案:
          • 硬件解決:增加帶寬(帶寬便宜)。
          • 軟件解決:分析對應(yīng)業(yè)務(wù)操作的數(shù)據(jù)傳送內(nèi)容是否可精簡;是否可以異步傳送。

          網(wǎng)絡(luò)連接狀態(tài)監(jiān)控

          性能測試中對網(wǎng)絡(luò)的監(jiān)控主要是監(jiān)控網(wǎng)絡(luò)連接狀態(tài)的變化和異常。
          • 對于使用 TCP 協(xié)議的服務(wù),需要監(jiān)控服務(wù)已建立連接的變化情況(即 ESTABLISHED 狀態(tài)的 TCP 連接)。
          • 對于 HTTP 協(xié)議的服務(wù),需要監(jiān)控被測服務(wù)對應(yīng)進程的網(wǎng)絡(luò)緩沖區(qū)的狀態(tài)、TIME_WAIT 狀態(tài)的連接數(shù)等。

          Linux 自帶的很多命令如 netstat、ss 都支持如上功能。
          下圖是 netstat 對指定 pid 進程的監(jiān)控結(jié)果:
          完整命令輸出:

          數(shù)據(jù)庫

          慢查詢

          更具體的慢 SQL 分析優(yōu)化,可參見《MySQL 慢 SQL & 優(yōu)化方案》。
          如 MySQL 資源出現(xiàn)瓶頸,首先找慢查詢(超過自定義的執(zhí)行時間閾值的 SQL)。
          1)通過 SQL 語句定位到慢查詢?nèi)罩镜乃谀夸洠缓蟛榭慈罩尽?/span>
          show variables like "slow%";
          2)慢查詢?nèi)罩驹诓樵兘Y(jié)束以后才紀(jì)錄,所以在應(yīng)用反映執(zhí)行效率出現(xiàn)問題時,查詢慢查詢?nèi)罩静⒉荒芏ㄎ粏栴}。這時可以使用show processlist命令查看當(dāng)前 MySQL 正在進行的線程狀態(tài),可以實時地查看 SQL 的執(zhí)行情況。
          示例:
          mysql -uroot -p123456 -h127.0.0.1 -p3307 -e "show full processlist" |grep dbname |grep -v NULL
          3)找到慢查詢 SQL 后可以用執(zhí)行計劃(explain)進行分析(或反饋給 DBA 和開發(fā)處理)。推薦最簡單的排查方式,步驟如下:
          1. 分析 SQL 是否加載了不必要的字段/數(shù)據(jù)。
          2. 分析 SQL 是否命中索引。
          3. 如果 SQL 很復(fù)雜,優(yōu)化 SQL 結(jié)構(gòu)。
          4. 如果表數(shù)據(jù)量太大,考慮分表。
          5. ……

          連接數(shù)

          數(shù)據(jù)庫連接池的使用率
          • 當(dāng)數(shù)據(jù)庫連接池被占滿時,如果有新的 SQL 語句要執(zhí)行,只能排隊等待,等待連接池中的連接被釋放(等待之前的 SQL 語句執(zhí)行完成)。
          • 如果監(jiān)控發(fā)現(xiàn)數(shù)據(jù)庫連接池的使用率過高,甚至是經(jīng)常出現(xiàn)排隊的情況,則需要進行調(diào)優(yōu)。
          查看/設(shè)置最大連接數(shù)
          -- 查看最大連接數(shù)
          -- 查看最大連接數(shù)
          mysql> show variables like '%max_connection%';
          +-----------------------+-------+
          | Variable_name         | Value |
          +-----------------------+-------+
          | extra_max_connections |       |
          | max_connections       | 2512  |
          +-----------------------+-------+
          2 rows in set (0.00 sec)

          -- 重新設(shè)置最大連接數(shù)
          set global max_connections=1000;
          在/etc/my.cnf 里面設(shè)置數(shù)據(jù)庫的最大連接數(shù)
          [mysqld]
          max_connections = 1000
          查看當(dāng)前連接數(shù)
          mysql> show status like  'Threads%';
          +-------------------+-------+
          | Variable_name     | Value |
          +-------------------+-------+
          | Threads_cached    | 32    |
          | Threads_connected | 10    |
          | Threads_created   | 50    |
          | Threads_rejected  | 0     |
          | Threads_running   | 1     |
          +-------------------+-------+
          5 rows in set (0.00 sec)
          • Threads_connected:表示當(dāng)前連接數(shù)。跟 show processlist 結(jié)果相同。準(zhǔn)確的來說,Threads_running 代表的是當(dāng)前并發(fā)數(shù)。
          • Threads_running:表示激活的連接數(shù)。一般遠低于 connected 數(shù)值。
          • Threads_created:表示創(chuàng)建過的線程數(shù)。
            • 如果我們在 MySQL 服務(wù)器配置文件中設(shè)置了 thread_cache_size,那么當(dāng)客戶端斷開之后,服務(wù)器處理此客戶的線程將會緩存起來以響應(yīng)下一個客戶而不是銷毀(前提是緩存數(shù)未達上限)。
            • 如果發(fā)現(xiàn) Threads_created 值過大的話,表明 MySQL 服務(wù)器一直在創(chuàng)建線程,這也是比較耗資源,因此可以適當(dāng)增加配置文件中 thread_cache_size 值。
          查詢服務(wù)器 thread_cache_size 的值
          mysql> show variables like 'thread_cache_size';
          +-------------------+-------+
          | Variable_name     | Value |
          +-------------------+-------+
          | thread_cache_size | 100   |
          +-------------------+-------+
          1 row in set (0.00 sec)

          詳見《MySQL 事務(wù)和鎖》。

          緩存命中率

          1. 通常,SQL 查詢是從磁盤中的數(shù)據(jù)庫文件中讀取數(shù)據(jù)。
          2. 若當(dāng)某一個 SQL 查詢語句之前執(zhí)行過,則該 SQL 語句及查詢結(jié)果都會被緩存下來,下次再查詢相同的 SQL 語句時,就會直接從數(shù)據(jù)庫緩存中讀取。(注意,MySQL 8 開始已廢棄查詢緩存功能。)
          監(jiān)控點
          • 業(yè)務(wù)執(zhí)行過程中 SQL 查詢時的緩存命中率(查詢語句讀取緩存的次數(shù)占總查詢次數(shù)的比例)。
          • 如果緩存命中率過低,需要優(yōu)化對應(yīng)的代碼和 SQL 查詢語句,以提高緩存命中率。

          案例分析

          測試結(jié)果分析
          結(jié)論:從目前的測試結(jié)果來看(如下圖所示),性能存在問題。
          現(xiàn)象:并發(fā)數(shù)達到 50 時的 TPS 為 52,此時雖然響應(yīng)時間為 4.4s(小于需求的 5s),但是數(shù)據(jù)庫服務(wù)器的 CPU 使用率非常高(接近 100%),因此需要重點關(guān)注數(shù)據(jù)庫的調(diào)優(yōu)分析。
          排查過程
          1. 使用 top 命令觀察,確定是 mysqld 導(dǎo)致還是其他原因
            • CPU 分為用戶 CPU 和內(nèi)核 CPU。綜合其他的各項資源指標(biāo)來分析,發(fā)現(xiàn)內(nèi)存、磁盤IO、網(wǎng)絡(luò)等指標(biāo)無任何異常,因此判斷此處不是內(nèi)核 CPU 占用高,主要原因是用戶進程占用的 CPU 高。
            • 確認目前 CPU 占用高的為 mysqld 進程。
          2. 分析數(shù)據(jù)庫服務(wù)器 CPU 高的可能原因:慢 SQL、SQL 語句過多、連接數(shù)過多等。
            • 使用show full processlist查看當(dāng)前數(shù)據(jù)庫中正在執(zhí)行的 SQL 語句及連接池的狀態(tài),發(fā)現(xiàn)大量 SQL 在等待執(zhí)行。
            • 再結(jié)合操作過程中的系統(tǒng)日志進行分析,發(fā)現(xiàn)每進入一次商城首頁,就需要在數(shù)據(jù)庫中執(zhí)行 19 條查詢 SQL。
            • 查看慢查詢?nèi)罩荆纯词欠裼谐^預(yù)期指標(biāo)的 SQL 語句,并分析排查:看看執(zhí)行計劃是否準(zhǔn)確、索引是否缺失、數(shù)據(jù)量是否太大等。
            • 目前案例經(jīng)過慢查詢?nèi)罩镜姆治觯创嬖诼樵儭?/span>
            • 確認是否存在慢 SQL:
            • 確認是否 SQL 語句過多或連接數(shù)過多:
          解決方案
          • 硬件解決:增加 CPU。
          • 軟件解決:為減少一次性加載過多 SQL,可考慮使用分批次、異步加載的方式(展示到什么位置,就查詢什么位置的數(shù)據(jù))。

          JAVA 應(yīng)用

          JVM

          JVM 簡介
          JVM(JAVA Virtual Machine):虛擬出來的空間,專門供 JAVA 程序運行。

          JVM 內(nèi)存
          重點關(guān)注:堆區(qū)(動態(tài)變化)
          所有的對象在初始化都會申請堆區(qū)的空間,如果已申請的空間在使用結(jié)束后沒有及時地釋放,那么該空間就會被占用,即內(nèi)存泄漏。
          監(jiān)控點:因此在測試時,需要關(guān)注堆區(qū)的空間是否持續(xù)上升而沒有下降。

          案例分析
          現(xiàn)象:堆內(nèi)存使用是持續(xù)升高,無法降低到之前的水平。
          解決方案:找到內(nèi)存泄漏的代碼,并優(yōu)化代碼。

          垃圾回收機制

          什么是垃圾回收機制
          • 垃圾回收指將內(nèi)存中已申請并使用完成的那部分內(nèi)存空間回收,供新申請使用。
          • 垃圾回收機制都是針對堆區(qū)的內(nèi)存進行的。
          監(jiān)控點
          • 系統(tǒng)在做垃圾回收時,不能夠處理任何用戶業(yè)務(wù)的。如果垃圾回收過于頻繁,導(dǎo)致系統(tǒng)業(yè)務(wù)處理能力下降。
          • 由于 Full GC 內(nèi)存比較大,垃圾回收一次時間比較長,那么這段時間內(nèi)都不能處理業(yè)務(wù),對系統(tǒng)影響比較大,因此我們需要關(guān)注Full GC 頻率。

          垃圾回收機制的運行步驟如下:
          1. 新程序執(zhí)行時需要先申請內(nèi)存空間,會先從年輕代中申請。
          2. 在年輕代滿了以后,就會進行垃圾回收Young GC。
          3. 回收時檢查年輕代中的內(nèi)存,是否還在使用。還在使用的部分會移存到生存區(qū) 2 中;不使用的部分則釋放,此時年輕代內(nèi)存空間被清空。
          4. 新程序執(zhí)行申請內(nèi)存空間,再從年輕代申請。
          5. 年輕代又滿了,就會進行垃圾回收Young GC。還在使用的內(nèi)存移存到生存區(qū) 1 中,并把生存區(qū) 2 中的內(nèi)存也都存到生存區(qū) 1 中。此時就會清空年輕代和生存區(qū) 2。
          6. 循環(huán)上述 1-5 步。
          7. 如果部分內(nèi)存在生存區(qū)中存活很久(內(nèi)存在生存區(qū)中移動了 10 次左右),則將這部分內(nèi)存放入到老年代中。
          8. 循環(huán)上述 1-7 步,直到老年代內(nèi)存空間全部占滿,此時就要進行垃圾回收Full GC。


            作者 |  Juno3550

          來源 |  cnblogs.com/juno3550/p/15212546.html


          加鋒哥微信: java1239  
          圍觀鋒哥朋友圈,天天推送Java干貨!

          瀏覽 53
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品——色哟哟 | 天堂一区二区三区18在线观看 | 加勒比无视频网站 | 影音先锋在线播放99av | 18成人网站在线观看 |