溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

記一次Grpc接口壓力測試&性能調(diào)優(yōu)

發(fā)布時間:2020-07-06 03:57:27 來源:網(wǎng)絡(luò) 閱讀:39089 作者:lilugoodjob 欄目:軟件技術(shù)

〇、經(jīng)驗總結(jié):

  • 如果在壓測過程中,壓力始終上不去,可以考慮是施壓機器并發(fā)上不去,或者被壓機器請求處理不過來。
  • 施壓上不去或者被壓機器請求處理不過來,是因為機器CPU瓶頸?內(nèi)存瓶頸?端口數(shù)量瓶頸?逐步排查定位。
  • 類似于Grpc這類需要建立rpc連接的請求,可擴展端口的數(shù)量會影響并發(fā)時連接建立數(shù)量。
  • 長鏈路的壓測鏈,在定位問題時可以先從短鏈開始逐步排查擴展到長鏈,最終完成整個鏈路的壓力測試。
  • 關(guān)注壓測過程中可能出現(xiàn)的異?,F(xiàn)象,哪怕是很不明顯的地方,都可能會存在一個BUG。

一、背景說明
這周我們對項目里新增的幾個接口進行了壓力測試,期間遇到了一些之前沒有遇到過的坑,走了一些彎路,在這里對這次壓力測試經(jīng)歷進行總結(jié)復(fù)盤,同時也希望能給看到這篇文章的諸位提供一些淺顯的思路。
首先介紹一下我們項目的結(jié)構(gòu)。服務(wù)入口是一個網(wǎng)關(guān)模塊,提供一個Grpc類型的接口,數(shù)據(jù)傳輸模式是一元數(shù)據(jù)模式。網(wǎng)關(guān)模塊與其他業(yè)務(wù)模塊之間通過Dubbo接口進行交互。
服務(wù)的架構(gòu)概況圖如下:
記一次Grpc接口壓力測試&性能調(diào)優(yōu)

該業(yè)務(wù)接口部署的服務(wù)器配置和部署MySQL組件的服務(wù)器配置一致,都是4核8G,50G普通硬盤,并且處于同一個內(nèi)網(wǎng)網(wǎng)段,我們預(yù)估的性能指標(biāo)要達到300并發(fā),600TPS。
在壓力測試過程中,我們重點關(guān)注TPS、GC次數(shù)、CPU占用率和接口響應(yīng)時間等指標(biāo)。

二、測試過程
完成項目部署后,我們開始編輯jemeter測試腳本,設(shè)置壓力測試的標(biāo)準(zhǔn)為300個并發(fā)線程,在10秒內(nèi)全部啟動,持續(xù)壓測時間15分鐘,接著開始啟動jemeter腳本進行測試。
1、第一次壓力測試
垃圾收集策略包括:老年代啟用CMS垃圾收集算法,新生代啟用ParNew垃圾收集算法,新生代最大存活周期為15次minorGC,F(xiàn)ullGC時使用CMS算法,并開啟CMS中的并行標(biāo)記。
根據(jù)前幾次的壓力測試經(jīng)驗,我們將初始堆內(nèi)存設(shè)置為2048MB,因為偏小的堆內(nèi)存設(shè)置容易在壓力測試時被撐爆。
JVM內(nèi)存分配:最大/最小堆內(nèi)存為2048MB,Eden和Survivor比例為8:2,新生代和老年代的比例為1:2。由于服務(wù)器安裝的是JDK8版本,廢棄了永久代的配置。
JVM配置參數(shù)如下:

-XX:+PrintGCDetails 
-XX:+PrintGCDateStamps 
-Xloggc:/var/log/$MODULE/gc.log 
-XX:+UseConcMarkSweepGC 
-XX:+UseParNewGC 
-XX:MaxTenuringThreshold=15 
-XX:+ExplicitGCInvokesConcurrent 
-XX:+CMSParallelRemarkEnabled 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/var/log/$MODULE 
-Xmx2048m -Xms2048m 
-XX:SurvivorRatio=8

(2)性能指標(biāo)監(jiān)控
top命令觀察java線程的CPU占用率(us表示用戶進程,sy表示系統(tǒng)進程),并使用jstac -gcutil Pid 1000 命令,定期查看虛擬機的GC情況。
一切準(zhǔn)備就緒后,我們開始跑壓測腳本,并查看性能監(jiān)控指標(biāo)。
但是我們沒有看到預(yù)期來臨的壓力,而是并發(fā)到達一定值時,好像突然并發(fā)壓力中斷了,然后間隔1-2秒后壓力又重新出現(xiàn),這期間接口服務(wù)器各項指標(biāo)均沒有異常。很顯然,并發(fā)存在問題!
記一次Grpc接口壓力測試&性能調(diào)優(yōu)

(3)問題排查與解決
上述壓測過程中出現(xiàn)的現(xiàn)象,可以細分為兩類:

  • 并發(fā)數(shù)量沒有達到預(yù)期值,而且徘徊在一個較低水平,壓測2分鐘,接口側(cè)只收到了3W多個請求,實際在施壓服務(wù)器嘗試發(fā)起了7W次請求。
  • 并發(fā)過程中出現(xiàn)類似壓力中斷的現(xiàn)象,而且并非偶然現(xiàn)象,壓力停頓之后壓測腳本中的斷言開始拋出錯誤信息:連接異常。
    異常信息如下:
    記一次Grpc接口壓力測試&性能調(diào)優(yōu)

由于Grpc接口需要在客戶端與服務(wù)端建立RPC連接,那么兩端都需要同時指定各自的一個端口進行數(shù)據(jù)通信?;谶@一點,我們判斷出現(xiàn)第一種現(xiàn)象的原因可能有兩個:

  • 施壓機器端口受限,沒有啟動足夠的線程發(fā)起請求;
  • 被壓機器端口受限,不能接收施壓機器發(fā)過來的所有請求連接,導(dǎo)致連接請求丟失。
    而出現(xiàn)第二種現(xiàn)象的原因,可能正是由于端口數(shù)量受限,并發(fā)線程不能正常發(fā)起,需要等待連接端口釋放后才能繼續(xù)發(fā)起新的連接線程。
    于是我們?nèi)ゲ榭磧啥藱C器的擴展端口列表,命令:
    cat  /proc/sys/net/ipv4/ip_local_port_range

    結(jié)果是:
    記一次Grpc接口壓力測試&性能調(diào)優(yōu)

即僅放開了 32768——60999 之間的端口,數(shù)量大致也是3W左右。
然后我們重新設(shè)置了被壓機器的端口擴展列表,命令:

echo  "10000    65535" >  /proc/sys/net/ipv4/ip_local_port_range

結(jié)果是:
記一次Grpc接口壓力測試&性能調(diào)優(yōu)

2、第二次壓力測試
經(jīng)過第一次壓力測試調(diào)整后,我們開始對調(diào)整效果進行測試驗證。
(1)JVM配置
JVM配置沒有改變
(2)性能指標(biāo)監(jiān)控
查看被壓機器的GC情況和CPU使用情況,依然沒有太大變化,但請求數(shù)量稍微有所提升,說明端口擴展有一定的效果,但是不明顯。
繼續(xù)查看施壓機器的信息,接口調(diào)用的結(jié)果斷言依然存在錯誤,雖然錯誤率有所降低(跟被壓機器接收請求的數(shù)量上升有關(guān)系),錯誤信息還是連接異常。

記一次Grpc接口壓力測試&性能調(diào)優(yōu)

從這個結(jié)果來看,解決問題的方向是對的,于是繼續(xù)把施壓機器的端口擴展放開,開始第三輪測試驗證。
3、第三次壓力測試
(1)JVM配置
JVM配置沒有改變
(2)性能指標(biāo)監(jiān)控
施壓機器和被壓機器的端口列表都放開后,grpc連接請求都正常了。在100并發(fā)和300并發(fā)兩種情況下,持續(xù)2分鐘發(fā)起的請求數(shù)相差不大,說明已經(jīng)接近了兩端服務(wù)器的處理極限了。
記一次Grpc接口壓力測試&性能調(diào)優(yōu)

(3)新問題暴露
本來以為這樣就OK了,然而此時突然發(fā)現(xiàn)被壓機器的GC開始出現(xiàn)異常,即YGC次數(shù)開始不變動,但是FGC頻繁。
壓測一段時間后,F(xiàn)GC開始出現(xiàn),頻率為平均每秒2-3次。
記一次Grpc接口壓力測試&性能調(diào)優(yōu)

通常出現(xiàn)FGC的原因,無非就是老年代被占滿了,于是查看線程的老年代堆內(nèi)存情況:

jstat -gcold  PID

記一次Grpc接口壓力測試&性能調(diào)優(yōu)
記一次Grpc接口壓力測試&性能調(diào)優(yōu)

我的天!老年代才64KB!這是把新生代內(nèi)存塞滿后,開始往可憐巴巴的老年代塞了,于是頻繁觸發(fā)FGC。
于是查看JVM參數(shù)配置,發(fā)現(xiàn)少了老年代的內(nèi)存配置了。
老年代的堆內(nèi)存配置可以通過 -XX:NewRatio=3 來設(shè)置,表示老生代:新生代的比值。即如果2GB堆內(nèi)存的話,那么老年代是1.5GB,新生代是0.5GB。
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/$MODULE/gc.log -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:MaxTenuringThreshold=15 -XX:+ExplicitGCInvokesConcurrent -XX:+CMSParallelRemarkEnabled -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/$MODULE -Xmx2048m -Xms2048m -XX:SurvivorRatio=8 -XX:NewRatio=3
配置好之后,重啟被壓測模塊,查看進程的堆內(nèi)存分配情況:
記一次Grpc接口壓力測試&性能調(diào)優(yōu)

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI