摘要:設計一個線上壓測系統能讓我們學習到多少東西?這13個問題看你能否搞定。 本文分享自華為雲社區《設計一個線上壓測系統能讓我們學習到多少東西?13個問題看你能否搞定》,作者:breakDawn。 Q: 為什麼需要線上壓測? A: 需要在某些活動、大促前,評估機器擴容數量,驗證系統能否有效支撐流量峰 ...
摘要:設計一個線上壓測系統能讓我們學習到多少東西?這13個問題看你能否搞定。
本文分享自華為雲社區《設計一個線上壓測系統能讓我們學習到多少東西?13個問題看你能否搞定》,作者:breakDawn。
Q: 為什麼需要線上壓測?
A:
- 需要在某些活動、大促前,評估機器擴容數量,驗證系統能否有效支撐流量峰值。
- 線下測試環境的機器資源有限, 無法完全模擬現網。 同時很多配置可能配置不相同,如果沒對上導致機器數量估計錯誤,可能引發重大故事。所以必須要線上上做壓測。
Q: 全鏈路壓測和介面壓測的區別?
A:
在特定的業務場景下,將相關的鏈路完整地串聯起來同時施壓,儘可能模擬出真實的用戶行為。
介面A做介面壓測,可能是1w/s的QPS, 但是A和B同時壓測,可能因為資料庫連接等共用資源,導致實際QPS下降。
Q: 業務系統如何區分壓測流量?即判斷哪些是壓測的請求,哪些是正常的請求?
A:
- url上加上打標參數, 例如 http://xx?st=true
- hearder中打標
Q: 這個壓測打標的改造和適配要中間所有服務參與嗎? 改造成本會不會有點大?
A:
不需要全部參與。
如果設計過鏈路跟蹤系統, 則每個服務都有中間件團隊提供的攔截器, 因此直接通過公共攔截器來做壓測標記的識別。
Q: 識別到壓測標記後, 如何保證往下游發請求時,仍然是壓測標記的形式?
即發請求的時候已經不是同一段攔截器的代碼了。 但是也要保證儘可能不改動原有的業務邏輯代碼。
A:
如果處理請求和發下游請求是在一個線程中完成的, 那麼可以使用threadLocal。
即攔截到請求時, 將壓測標記set進threadLocal中。
發送下游請求的代碼中,如果能從threadLocal中拿到壓測標記,則改造url,設置進往下發的請求中
Q: 如果我不在同一個線程中處理和發請求, 怎麼辦?
即我的業務代碼中 做了new Thread或者ExectorPool.submit提交非同步請求, 這時候業務邏輯里肯定不會涉及到threadLocal的代碼, 而此時壓測標記就會丟失了。
threadLocal可以用 InheriableThreadLocal, 這樣如果線上程中new新的線程,則標記可以被傳遞下來。
如果是線程池創建非同步請求, 可以用阿裡的TransmittableThreadLocal。
Q: 如果我的壓測鏈路中 包含了外部服務的介面怎麼辦? 例如第三方支付、第三方簡訊等。
A:
鏈路跟蹤系統中發請求的filter中, 新增MockFilter, 如果判斷是壓測請求, 則直接返回mock邏輯(不建議部署mock服務, 因為部署mock服務的話,伺服器成本又得考慮,不如直接封裝到mockFilter代碼中)
Q: 會對資料庫產生影響的壓測請求怎麼辦?
如果直接落庫,可能會影響正常用戶的請求訪問, 也可能污染線上數據。
A:
為每個生產庫 生成一個影子庫, 專門用來存儲壓測數據。
然後做過分庫分表的話, 肯定有資料庫的proxy,在proxy里都往壓測庫插入和讀寫。
如果沒有,就擴展Spring的AbstactRoutngDataSource類, 實現一個動態的數據源,讓裡面可以根據壓測標記進行切換。
Q: redis、kafka等中間件對壓測有什麼特殊處理?
A:
除了添加統一特點的壓測標記(中間件和業務不是強相關,所以可以進行特定改造)
還要註意緩存的存活時間要設置短一點。
Q: 壓測結束時,如何避免對資料庫繼續產生影響?
A:
註意不要觸發 數據源的init-method方法, 當真正執行壓測的時候再建議會話連接。
各種超期時間也要註意設置, 儘快接觸壓測對組件的影響。
Q: 壓測數據怎麼構造?一個個手動拼數據參數,然後讓測試同學發送嗎?
A:
不行,如果業務有改動,參數很容易對不上,同時組裝過程耗時也會非常久。
建議從線上直接dump最近的請求數據,這樣可保證參數沒有變化。
同時做一些脫敏和修正處理。
Q: 怎麼完整設計這個壓測系統的架構?包含哪些角色
A:
該問題參考《超大流量分散式系統架構解決方案》一書中給出的方案,也可以有其他方案。
- 壓測manager服務, 提供給壓測控制者查看和使用的。可以讀取mysql資料庫獲取壓測結果情況,或者進行調度指令的下發等。
- taskService服務,用於處理調度指令,執行定時調度、即時調度等行為。
- Agent 壓測請求發送客戶端。根據taskService的指令進行發送
- DataFactoy,給agent提供脫敏、修改後的壓測數據。
- MQ, 接收agent壓測請求的結果,堆積到隊列里提供給DataCollect消費。
- DataCollect, 壓測結果消費者, 將結果寫入到資料庫MYSQL。
- 註冊中心,用於管理和註冊上面這些服務。
- Detecotr, 流量檢測和干預器,可以根據情況即時調整agent的發送速率。
Q: 怎麼模擬實際用戶的請求發送? 因為實際場景應該是多個不同ip的用戶訪問進來才對。
A:
- apache HttpComponents的httpclient包
- Java11的非同步httpclient, 支持HTTP/2, 支持用reactive stream。