1,基礎:
目標:發現系統瓶頸,進行容量規划
原則:不影響正常業務的運行
2,實施流程:
1)基礎中間件開發
2)測試同學梳理核心接口准備壓測腳本,根據真是情況分配調用比率等
3)業務升級與線下驗證(人工點擊,數據落影子庫)
4)影子數據准備,運維同學進行壓力機及內網負載均衡准備
5)小流量預發驗證(用 jmeter 下發,數據落影子庫)
6)大流量生產環境壓測
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根據當前是否為壓測選擇不同的數據鏈接
4,代碼改造:
1,壓測場景下打印的日志會影響數據部門各類指標的計算,代碼改造判斷壓測場景下不打印日志
2,直接使用HashMap緩存數據的部分改造成使用Guava緩存,保證壓測場景的數據不影響正常的緩存
3,去掉spring-mvc.xml中的annotation-driven配置節,否則會影響壓測標識的傳遞
4,如果存在Filter替換為HandlerInterceptor,中間件使用了HandlerInterceptor進行攔截且排首位,所以獲取到正確的壓測標識也要使用HandlerInterceptor
5,數據准備:
1,還原相關的數據庫,要求備份時間相同。廣告投放有個特殊場景:針對費用,庫存等的大量消耗的會觸發Redis發消息使center更新ES可投放廣告,但是Redis的pubsub不區分Index導致錯誤更新正常的數據,在壓測時使用了更新費用為Max的方式保證ES的數據不變更。最優方案還是修改消息的發送消費使用MQ
2,存在兩個系統通過Redis進行數據交換,但是redis中的數據是使用定時任務刷新方式寫入不存在壓測觸發的場景,壓測時臨時開發接口手動觸發。建議開發時使用調用方自己維護緩存的方式
3,ES中的數據使用elasticdump進行導出導入再處理
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%。