全鏈路壓測軍演系統 ForceBot

hyl0711 7年前發布 | 20K 次閱讀 Git nGrinder 軟件架構 gRPC

一、ForceBot 愿景

1. 誕生背景

伴隨著京東業務的不斷擴張,研發體系的系統也隨之增加,各核心系統環環相扣,尤其是強依賴系統,上下游關系等緊密結合,其中一個系統出現瓶頸問題,會影響整個系統鏈路的處理性能,直接影響用戶購物體驗。

往年的618、雙11大促備戰至少提前3個月時間準備,投入大量的人力物力去做獨立系統的線上壓力評測,帶來的問題就是各個性能壓測團隊工作量非常大,導致壓測任務排期。

壓測的數據跟線上對比不夠準確,各個強依賴系統上下游需要在壓測中緊密配合,一不小心就會影響線上,有的在線下測試環境壓測,壓測出的數據更是跟線上差距太大,只能作為參考。

更重要的一個問題是各系統容量規劃,每次大促前備戰會必不可少的討論話題就是服務器資源申請擴容問題,各團隊基本都是依據往年經驗和線上資源使用率給出評估量,提出一個擴容量需求,導致各個業務系統每次促銷擴容量非常大。

為了解決以上各種苦惱,2016年基礎平臺部整體牽頭啟動了 ForceBot 全鏈路壓測(備戰常態化)這個項目。

此項目牽扯到所有京東研發體系團隊,各系統必須改造識別壓測過來的流量和線上正式流量進行區分標記特殊處理,不能因為壓測流量影響正常用戶體驗和污染線上數據等工作,由于跨團隊協作之多、跨系統協調改造等工作量非常大,挑戰性可想而知!

2. 能做什么

2016年主要實現了訂單前的所有黃金鏈路流程高并發壓測用戶行為模擬,包括模擬用戶操作:首頁、登陸、搜索、列表、頻道、產品詳情、購物車、結算頁、京東支付等。

在黃金鏈路中有各種用戶行為場景,比如一般用戶首先訪問首頁,在首頁搜索想要產品,翻頁瀏覽,加入購物車、湊單、修改收貨地址、選擇自提等等。

各系統壓測量依據往年雙11峰值作為基礎量,在此基礎上動態增加并發壓力;同時要區分對待兩個大的場景,日常流量和大促流量。

大促場景下搶購活動集中,交易中心寫庫壓力最大,另外用戶行為和日常有很大的反差,比如用戶會提前加入購物車,選擇滿減湊單,集中下單等等場景。

2016年啟用的鏈路較短,在2017年將實現訂單后生產的全鏈路。

3. 價值體現

ForceBot 在2016年雙11替代往年各系統獨自優化、性能壓測備戰狀態,目前所有的備戰數據和各系統性能承載能力、資源規劃等都由 ForceBot 給出直接數據作為依據,在軍演壓測過程中,秒級監控到壓測源、壓測中、京東所有的黃金鏈路系統、接口響應時間、TPS、TP99 等數據,軍演完成后提供豐富的壓測報告,準確的找到各系統并發瓶頸。

同時也承擔了內網單一系統的日常壓測任務,開放給研發和壓測團隊,支撐京東所有的壓測場景統一壓測平臺,對公司內壓測資源的整合和提高利用率。

二、 ForceBot 技術架構

工欲善其事,必先利其器。全鏈路壓測必須要有一套功能強大的軍演平臺,來實現自動化、全鏈路、強壓力的核心目標。

第一代性能測試平臺

基于 Ngrinder 做定制開發。Ngrinder 是一個 java 語言開源的、分布式性能測試平臺。它由一個 controller、多個 agent 組成,在 controller 建立測試場景,分發到 agent 進行壓力測試,壓力源將壓測數據上報給 controller。

Ngrinder 基于開源的 java 負載測試框架 grinder 實現,并對其測試引擎做了功能提升,支持 python 腳本和 groovy 腳本;同時提供了易用的控制臺功能,包括腳本管理、測試計劃和壓測結果的歷史記錄、定時執行、遞增加壓等功能。

我們根據京東的業務場景對 Ngrinder 進行了優化,以滿足我們的功能需求。比如:提升 agent 壓力,優化 controller 集群模式,持久化層的改造,管理頁面交互提升等。

Ngrinder 能勝任單業務壓測,但很難勝任全鏈路軍演壓測。分析其原因是 controller 功能耦合過重,能管理的agent數目有限。原因如下:

  • controller 與 agent 通訊是 bio 模式,數據傳輸速度不會很快;

  • controller 是單點,任務下發和壓測結果上報都經過 controller,當 agent 數量很大時,controller 就成為瓶頸了。

說的通俗點, controller 干的活又多又慢,整體壓力提升不上去。

盡管我們優化了 controller 集群模式,可以同時完成多種測試場景。但是,集群之間沒有協作,每個 controller 只能單獨完成一個測試場景。由此,我們著手研發全鏈路軍演壓測系統(ForceBot)。

ForceBot架構

新平臺在原有功能的基礎上,進行了功能模塊的解耦,鏟除系統瓶頸,便于支持橫向擴展。

  • 對 controller 功能進行了拆解,職責變為單一的任務分配;

  • 由 task service 負責任務下發,支持橫向擴展;

  • 由 agent 注冊心跳、拉取任務、執行任務;

  • 由 monitor service 接受并轉發壓測數據給 JMQ;

  • 由 dataflow 對壓測數據做流式計算,將計算結果保存在 db 中;

  • 由 git 來保存壓測腳本和類庫。GIT 支持分布式,增量更新和壓縮

這樣極大的減輕了 controller 的負載壓力,并且提升了壓測數據的計算能力,還可以獲取更多維度的性能指標。

在此基礎上,還融合進來了集合點測試場景、參數下發、tps 性能指標等新特性。下面將重點介紹以下幾個功能:

1. 容器部署

為了快速的創建測試集群,Agent 采用 docker 容器通過鏡像方式進行自動化部署。這樣做好處如下:

  • 利用鏡像方式,彈性伸縮快捷;

  • 利用 Docker 資源隔離,不影響 CDN 服務;

  • 每個 Agent 的資源標準化,能啟動的虛擬用戶數固定,應用不需要再做資源調度;

問題:Git 測試腳步如何在各個 Docker 之間共享。

解決方案:采用外掛宿主機的共享磁盤實現

2. 任務分配

用戶在管理端創建一個測試場景,主要包括:壓力源(分布在不同機房的壓力機)、虛擬用戶數、測試腳本、定時執行時間、process 的 jvm 參數,壓力源,啟動模式,集合點設置,選擇測試腳本。

這個測試場景保存到 db 后,controller 按照時間順序,掃描發現有測試場景了,會根據標簽算法尋找當前存活的空閑的 agent 資源,并計算 agent 的每個 worker process 啟動的線程數。

任務分配時,要考慮集合點的計算,就是虛擬用戶數在不同的時間點不斷變化。目前有兩種方式: 毛刺型和階梯型。

  • 毛刺型,就是在某個時間點有大量的請求瞬時訪問業務系統,這樣做可以測試系統的并發能力和吞吐量。

  • 階梯型,就是在相等時間間隔,虛擬用戶數等值遞增。

比如:一個測試場景在今天9點執行10000個虛擬用戶數,執行到9點01分要虛擬用戶數變為20000個,到9點05分虛擬用戶數又變為40000個,到9點07分虛擬用戶數變為10000個。虛擬用戶數像毛刺一樣上下變化。

上面的表格就是對應表結構設計,每個壓力線會按照順序保存到 db 中。在這張表中,只記錄的持續時間,具體的執行時間是由 controller 根據開始壓測時間累加持續時間逐一計算出來。execType 還包含了緩慢加壓減壓兩種類型,覆蓋了階梯型,默認時間間隔為5秒。

controller 要計算出每個間隔的執行時間點,遞增的虛擬用戶數。controller 將計算結果分給每個 agent,保存到 db 中,由 agent 定時來拉取。

動態加壓減壓目前只支持采用 Agent 的增減方式來實現。

問題:由于購物車是用戶共享的,在壓測下單過程中,同一個用戶并發操作會出現沖突。

解決方案:為每個壓測線程綁定使用不同的用戶。在任務分配過程中,為每個 process 進程中的線程分配線程編號。不同的線程根據編號,按照映射規則,找到相應的壓測用戶。

3. 心跳任務和下發

task service 為 agent 提供了任務交互和注冊服務,主要包括agent注冊、獲取任務、更新任務狀態。

Agent 啟動后就會到 task service 注冊信息,然后每個幾秒就會有心跳拉取一次任務信息。controller 會根據注冊的信息和最近心跳時間來判斷 agent 是否存活。

Agent 拉取任務和執行任務過程中,會將任務狀態匯報給 task service。controller 會根據任務狀態來判斷任務是否已經結束。

task service 采用了 GRPC 框架,通過接口描述語言生成接口服務。GRPC 是基于 http2 協議,序列化使用的是 protobuf3, java 語言版采用 netty4 作為網絡 IO 通訊。使用 GRPC 作為服務框架,主要原因有兩點:

  • 服務調用有可能會跨網絡,可以提供http2協議;

  • 服務端可以認證加密,在外網環境下,可以保證數據安全。

4. Agent的實現

Agent 職責主要是注冊,獲取任務信息,更新任務狀態,執行和停止 worker process 進程,同時上報壓測數據。通信協議主要是 GRPC。

  • Agent 啟動后生成 UUID 作為當前 Agent 的唯一標識,并向 Task Service 進行注冊。如果 Agent 進程掛掉重啟后,會產生新的 UUID ,放棄原來的任務。

  • Agent 心跳線程每隔3秒從Task Service 拉取任務。獲取到任務后,會把任務扔到隊列里面,并上報任務接收狀態,不阻塞當前拉取線程。

  • 任務執行線程從隊列獲取任務,如果是啟動新的測試任務,則先從 Git 拉取任務所需的腳本文件和用戶的自定義類庫。然后根據 jvm 參數,設置并啟動 worker process 進程,同時將任務的執行時間,虛擬用戶數,集合點設置信息,壓測腳本信息,以及腳本加載 plugin 所需要的 classpath 傳遞給 worker process。

    在這里我們采用使 Agent 通過 stdout 的方式與 Worker process 對 stdin 的監聽構成一個數據傳輸通道,采用 Stream 的方式將任務的所有信息和數據發送給 Worker process,使 Worker process 可以獲取到足夠且結構化的數據以完成初始化的工作。

問題:一臺物理機上多個 Docker 實例,如何減少更新測試腳步造成的 GIT 壓力?

解決方案:測試腳步存放到宿主機共享存儲,更新前,按照測試任務編號進行文件鎖,如果鎖成功則調用 Git 更新。同一個測試任務就可以減少 GIT 壓力。

問題:如何模擬在某一個瞬間壓力達到峰值?

解決方案:通過集合點功能實現,提前開啟峰值所需足夠數量的線程,通過計算確定各個時間點上不需要執行任務的線程數量,通過條件鎖讓這些線程阻塞。當壓力需要急劇變化時,我們從這些阻塞的線程中喚醒足夠數量的線程,使更多的線程在短時間進入對目標服務壓測的任務。

5. 數據收集和計算

實現秒級監控。數據的收集工作由 monitor service 完成,也是采用 GRPC 作為服務框架。agent 每秒上報一次數據,包括性能,JVM 等值。

monitor service 將數據經 JMQ 發送給 dataflow 平臺,進行數據的流式計算后,產生 TPS,包括 TP999,TP99,TP90,TP50,MAX,MIN 等指標存儲到 ES 中進行查詢展示。

問題:為了計算整體的 TPS,需要每個 Agent 把每次調用的性能數據上報,會產生大量的數據,如何進行有效的傳輸?

解決方案:對每秒的性能數據進行了必要的合并,組提交到監控服務。

三、業務系統改造

1. 黃金流程業務

首期識別從用戶瀏覽到下單成功的黃金流程,其包含的核心業務如下:

2. 壓測流量識別

壓測流量是模擬真實用戶行為,要保障在軍演過程中不能污染線上各種統計等數據,比如:PV UV 訂單量等,更不能影響正常用戶下單購物體驗。

首先要對用戶、商品進行打標,以便于各個系統進行測試流量識別。針對下單壓測,庫存系統需要根據測試用戶和商品提前準備好庫存量。風控系統需要放行測試用戶和商品的操作。

3. 壓測數據存儲

業務系統識別出壓測數據后,根據不同的場景,采用兩種方式來存放壓測數據。

  • 打標數據并存儲到生產庫中,壓測的數據能體現生產環境性能。定期清理測試數據。統計報表要過濾掉測試數據。改方案能利用現有資源,需要系統進行較多改造。

  • 構造壓測庫環境,根據壓測流量,把壓測數據存放到壓測庫中進行隔離。改方案需要較多的資源,但系統改造量小。支付系統最大的改造困難就是銀行接口的強依賴,不能用真實的銀行卡扣款和支付, ForceBot 的目標不是壓銀行接口,而是壓自己本身的支付系統,所以京東這邊支付團隊目前是自己造了一個假銀行,假接口,通過前端傳遞過來的壓測標識,自動路由到假銀行進行扣款支付;

四、ForceBot未來規劃

ForceBot 未來的路還很長,要做的優化、功能也很多,比如有:

  • 無人值守智能壓測,通過監控系統監控到各個被壓系統的性能問題,如遇到系統瓶頸問題聯動 JDOS 系統彈性擴容 docker 資源,擴容到一定量級后發現性能沒有提升,停止此壓測,由 callgraph 自動找到性能系統位置;

  • 人工智能預言:根據大數據人工智能學習計算,在 ForceBot 中設定訂單量目標值(秒級訂單量、日訂單量等),根據日常的軍演數據自動計算出各鏈路系統將要承載的軍演并發量,給出智能評估各系統的瓶頸所在,預測各系統的性能指標和瓶頸問題。

 

 

來自:http://mp.weixin.qq.com/s/cQjyXiuVODHsjQRzFO9k3w

 

 本文由用戶 hyl0711 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!