天天看點

性能壓測與調優

        性能壓測是當服務上線前,或者之後重要需求釋出流程中,需要做的必要測試;以模拟真實流量的方式,擷取目前系統的性能名額、是否存着高并發隐患、瓶頸等資訊的手段。

性能壓測處于什麼位置?或者說什麼時候去做呢?如何做?

如何做好線上環境的性能壓測、全鍊路壓測,如何做到壓測結果準确無誤,不影響外部環境、不污染資料,需要深入思考。

一、測試分類

按照上線流程:

  • 單元測試
  • 內建測試
  • 相容性測試(前端、用戶端)
  • 性能測試

運維階段:

  • 安全測試
  • 容災測試(故障恢複測試)

由上可以看出,性能測試是應用服務在上線過程中的一個流程,除非是内部系統,通路量少,否則都應當做一下性能測試。

安全測試又叫滲透測試,是運維和研發需要關注的問題;尤其是對資料安全要求高的系統。當一個服務穩定運作後,模拟一些攻擊手段,防止SQL注入、網絡攻擊、腳本攻擊等。

容災測試是容災方式的驗證,容災方式包括:雙機房建設、異地多活、兩地三中心。

二、壓測目的

  • 了解吞吐量
  • 瓶頸值
  • 系統隐患

可用:一次請求,到達伺服器,有回應;那麼針對這次請求,服務是可用的,無論傳回成功或者失敗。

不可用是指請求沒有傳回,長時間等待,沒有應答,用戶端不知道結果。

高可用級别:99%、99.9%、99.99%、99.999%

大家經常說的系統可用性達到三個9,就是指99.9%。

高可靠:是指服務可靠,資料可靠。請求傳回是成功,資料寫入正确,分布式環境下資料一緻性等。

三、壓測名額

性能壓測與調優

四、實作流程

1. 壓測工具選型

    Jmeter + Influxdb + Grafana + Collectd  

2.壓測環境準備

  • 服務環境
  • 壓測機
  • 資料庫
  • Redis
  • MQ

3.壓測資料準備

  • 日活資料:資料要真實、流量真實,結果才能越接近線上真實性能名額。
  • 資料隔離:防止污染真實使用者資料
  • 資料恢複
  • 熱點資料
  • 壓測預熱:盡量模拟線上真實環境情況,如緩存命中率

4.壓測開發設計

  • 擋闆
  • Mock資料
  • 流量識别
  • 壓測場景
  • 加壓政策

擋闆:是用來攔截調用第三方的請求,防止壓測對第三方造成影響;提前設計好擋闆邏輯,識别壓測流量,執行擋闆邏輯,并且為了真實,還可以合理延遲一定時間再傳回Mock資料。

流量識别:nginx做負載均衡,upstream 轉發伺服器ip 時,可以擷取http請求Header的參數,我們可以給壓測流量header加标記參數,nginx擷取參數判斷後,轉發壓測流量到壓測機器。

5.監控

監控很重要,可以說是壓測中最為重要的地方,如果沒有監控,或者監控不準确,會嚴重影響壓測本身準确性。監控資料不詳細,也會影響性能調優。

一般我們需要監控的如下:

  • CPU、記憶體
  • IO:網絡、磁盤
  • Http請求、接口方法
  • JVM
  • 中間件
  • 資料庫負載
  • 帶寬占用

其中對接口和方法的監控需要有,而且要準确,是定位性能問題的有效手段,越細化越好。

以下是一些監控工具:

1. Grafana 監控 (CPU、記憶體、成功率、http請求的RT)

性能壓測與調優

2. Sentinel 監控 (接口、方法級别)

性能壓測與調優

3. Visualvm 監控JVM

性能壓測與調優

通過上圖可以直覺的看出JVM堆記憶體的增長情況和GC回收頻率、回收後記憶體大小。如果回收後的記憶體在持續增高,且目前請求沒有增長,說明有記憶體洩露,具體什麼對象洩漏,需要通過jmap等指令,檢視堆記憶體heap的詳情。

如以下指令:

性能壓測與調優

對比GC前後的對象數量,分析是哪些沒有回收。

五、性能優化

注意:

  • 慎重優化,謹記二八原則 和 Amdahl定律。
  • 優化一定要伴随着壓測,通過性能名額、資料對比來論證和調整,否則沒有意義。

優化目标

  • 提升吞吐量
  • 降低 RT

優化方向

  • 硬體層面:CPU、記憶體擴容、換SSD固态硬碟
  • 軟體層面:叢集擴容、代碼優化、存儲優化(緩存、資料庫)、減少IO

優化方式

  • 代碼優化:請求合并、異步、Cache、池化
  • JVM調優
  • Linux調優

JVM調優

1. 調優關注點

  • 減少JVM不可用時間:STW(Stop the word)
  • GC 頻率
  • 安全點SafePoint

安全點是需要注意的問題,很多初學者會忽略安全點線程等待時間,其實STW時間包括安全點等待時間。

2. 常用GC回收器

  • ParNew + CMS     (低延遲、低核、小記憶體場景)
  • G1                         (高吞吐量、高核、大記憶體)

G1隻有在多核CPU,大記憶體情況下,才能展現出它的優勢,如果記憶體過小,表現反而不如ParNew+CMS。

那麼到底多大算大記憶體呢?

根據R大給出的建議是:以堆記憶體8g為限,大于8g用G1,小于8g用CMS。

3. JVM參數分類

  • -:标準參數,所有JVM都必須實作,且向後相容。
  • -X :非标準參數,預設JVM實作該參數,不保證向後相容。
  • -XX:非stable參數,不同JVM有所不同,将來可能會取消。

4. G1關鍵參數

-Xms16g   -Xmx16g   

-XX:+UseG1GC    -XX:MaxGCPauseMillis=50    -XX:InitiatingHeapOccupancyPercent=60   

-verbose:gc    -Xloggc:logs/gc_%p.log    -XX:+DisableExplicitGC

-XX:-UseLargePages  -XX:+PrintGCApplicationStoppedTime  -XX:-OmitStackTraceInFastThrow 

-XX:+PrintSafepointStatistics  -XX:PrintSafepointStatisticsCount=1
           

需要注意的是,G1最好不要加新生代大小參數 -Xmn ,如果固定了新生代大小,G1就沒法根據 -XX:MaxGCPauseMillis 設定的最大期望GC時間,動态調整堆記憶體的新生代和老年代大小,相當于-XX:MaxGCPauseMillis 失效了。除非你很熟悉G1原理,加了新生代大小,配合其他參數,也可以調優出一個不錯的結果。否則還是交給G1本身的自動調整吧。

5. GC 日志

2020-01-09T11:05:34.836+0800: [GC pause (G1 Evacuation Pause) (young) ……
[Eden: 8576.0M(8576.0M)->0.0B(8576.0M) Survivors: 16.0M->16.0M Heap: 8643.7M(14.0G)->68.2M(14.0G)]
[Times: user=0.05 sys=0.04, real=0.02 secs]
2020-01-09T11:05:34.863+0800: 2043140.818: Total time for which application threads were stopped:0.0286394 seconds, Stopping threads took: 0.0002674 seconds
2020-01-09T12:01:10.488+0800: 2046476.443: Application time: 3335.6250688 seconds
2020-01-09T12:01:10.490+0800: 2046476.444: [GC pause (G1 Evacuation Pause) (young) 2046476.444:
           

gc日志中 Stopping threads took 就是安全點時,線程的等待時間,是以STW時間應該是:GC時間 + 安全點等待時間。

如果 Stopping threads took 較大,說明代碼程式是有問題的,需要深入檢視;

具體什麼情況會導緻安全點時間過長,請參考:

JVM安全點介紹

HBase實戰:記一次Safepoint導緻長時間STW的踩坑之旅

Linux調優

我在對業務項目、RocketMQ、Redis、codis叢集、Elasticsearch、Hbase等進行優化過程中,經常遇到一些相同的問題,我總結了下,主要有以下:

  • 慎用交換區swap

        優化方式:禁止swapping 或者設定 swappiness = 1

        swapping會導緻gc過程從毫秒級變成分鐘級

  • 善用 /dev/shm/

       /dev/shm/ 是linux的檔案記憶體系統,是共享記憶體,直接從實體記憶體中開辟,根據使用情況會動态擴容。

針對一些寫入檔案,IO性能要求高的場景,可以使用/dev/shm/,例如gc日志存放。

高并發場景下,如果打開安全點日志,安全點日志是在安全點内列印,是同步的,是以日志寫入檔案速度,會嚴重影響gc快慢;應當将gc日志配置改為:

-Xloggc:/dev/shm/gc_%p.log 
           

其他linux調優,一般大點的公司,都會有自己的運維團隊,運維就會做基本的優化,例如tcp連接配接優化等,這裡隻介紹運維可能忽略的,不知道的點,這時候就需要研發同學介入,找運維做好應用相關的Linux核心優化。

繼續閱讀