全鏈路壓測實踐

1,基礎:
目標:發現系統瓶頸,進行容量規劃
原則:不影響正常業務的運行git

2,實施流程:
1)基礎中間件開發
2)測試同窗梳理核心接口準備壓測腳本,根據真是狀況分配調用比率等
3)業務升級與線下驗證(人工點擊,數據落影子庫)
4)影子數據準備,運維同窗進行壓力機及內網負載均衡準備
5)小流量預發驗證(用 jmeter 下發,數據落影子庫)
6)大流量生產環境壓測github

3,基礎組件:
1)線程變量的設置與傳遞:經過HandlerInterceptor攔截客戶端請求,若是cookie或者querystring有壓測標識則經過TransmittableThreadLocal存儲壓測標識,並使該攔截器要求註冊在首位保證後續的處理流程能獲取到正確的壓測標識,TransmittableThreadLocal可以保證使用線程池時線程變量的正確傳遞(https://github.com/alibaba/transmittable-thread-local)。 經過Dubbo的Filter或者RequestTemplate的header傳遞到遠程。
2)基於AOP攔截數據源:攔截MongoTemplate建立影子實例,攔截RocketMQ或ONS發送時添加UserProperties,接收後若是發現有壓測標識設置線程變量
3)基於ByteBuddy攔截(Redis和Guava等不是經過容器建立的實例:Redis在方法執行先後切換Index在當前的Index上加1。Guava的處理比較特殊,壓測流量致使的緩存回源將使緩存的是影子數據庫的數據因此只能以正常請求爲主,在Guava的load,reload執行前設置壓測標識爲false經過新的ThreadLocal存儲原始的壓測標識,在方法執行後恢復ThreadLocal中存儲的值
4)基於BeanPotProcessor的封裝:對使用的common-dbcp中BasicDataSource進行二次封裝,實現AbstractRoutingDataSource的determineCurrentLookupKey根據當前是否爲壓測選擇不一樣的數據連接web

4,代碼改造:
1,壓測場景下打印的日誌會影響數據部門各種指標的計算,代碼改造判斷壓測場景下不打印日誌
2,直接使用HashMap緩存數據的部分改形成使用Guava緩存,保證壓測場景的數據不影響正常的緩存
3,去掉spring-mvc.xml中的annotation-driven配置節,不然會影響壓測標識的傳遞
4,若是存在Filter替換爲HandlerInterceptor,中間件使用了HandlerInterceptor進行攔截且排首位,因此獲取到正確的壓測標識也要使用HandlerInterceptorredis

5,數據準備:
1,還原相關的數據庫,要求備份時間相同。廣告投放有個特殊場景:針對費用,庫存等的大量消耗的會觸發Redis發消息使center更新ES可投放廣告,可是Redis的pubsub不區分Index致使錯誤更新正常的數據,在壓測時使用了更新費用爲Max的方式保證ES的數據不變動。最優方案仍是修改消息的發送消費使用MQ
2,存在兩個系統經過Redis進行數據交換,可是redis中的數據是使用定時任務刷新方式寫入不存在壓測觸發的場景,壓測時臨時開發接口手動觸發。建議開發時使用調用方本身維護緩存的方式
3,ES中的數據使用elasticdump進行導出導入再處理spring

6,問題總結:
總體思路:壓測時觀察應用服務器外部數據源的RT,資源使用狀況,計算型的瓶頸會致使CPU滿載,外部IO型的瓶頸會致使load變高和RT增大。經過CAT查看各個接口以及外部數據源的訪問RT是否隨着請求量的增長而提升,若是RT有變高說明有性能問題。
1),Redis過分調用(一次發券對應活動web的10次以及engine的20左右的redis訪問):
大部分數量量較小且實時性要求不高的數據能使用內存緩存異步刷新的場景沒有使用內存緩存
針對用戶級別的短期限流和有效性驗證能夠經過粘性用戶到指定機器加內存緩存的方式解決
2),緩存粒度或者緩存層級不正確:
活動web調用center獲取活動獎項,返回的是排序後的獎項,可是緩存的是未排序的數據庫查詢又在內存進行一次排序。
獎項或導航頁的信息經過內存緩存在center層,web層到center存在大量的調用獲取緩存的信息,可是針對實時性要求不高且數據量不大的場景應該使用內存緩存直接緩存在web層,若是實時性要求較高且數據量不大可使用內存緩存加MQ變動通知的方式
3),設計缺陷:
計費系統在廣告計費後發送變動消息由投放系統校驗廣告配置包消耗和時段限制,若是投放系統的實例多則會致使同時多機同時運算,實際應該由計費系統計算後發送MQ投放系統接受後直接更新內存緩存
活動web的getToken接口在調用量大的場景下致使cpu滿負荷,該接口在每次參與抽獎時生成token和一段JS組合加密後返回,加密操做運算量很大。優化後將JS加密後緩存每次只加密生成的token,性能提高10倍左右。
4),調用鏈路優化:
廣告發券時每次都須要調用商品中心取券,從業務上分析對於佔大多數的推廣連接類型的廣告沒有券控制,優化後對商品中心的調用量減小90%。數據庫

相關文章
相關標籤/搜索