在組里,我負責一個推送通知系統,這個系統主要的功能就是提醒客戶端是否該拉去最新的數據,3周前,上線了新的功能,經過staging環境的詳細測試通過,全部部署上線后,每天會受到snmp.udp.inError報警,這是每臺服務器內置監控的報警,表示udp包沒有及時處理,我們系統內部都是udp通信的。通過監控界面查看,不是特別頻繁,丟包率不到1%,而且我們udp網絡庫應用層做了重傳,不影響業務層邏輯。查看歷史記錄,之前很少,沒這么頻繁,這個監控理論上應該為0,從改動上來看,功能上沒啥太大變化,不應該出現這個問題。
首先影響服務器的性能因素:
cpu:體現為多線程,多進程充分利用多核,提高并發性能
內存:現在內存的訪問速度很快,速度不是問題,內存不足時,系統會內存置換,比較影響性能
網卡:網絡流量打滿了網卡,多余的請求就沒法被處理。
鎖:鎖本身并不會影響性能問題,鎖的等待比較影響。
-
同步阻塞IO:如果某一個同步操作很費事,所有的后續操作被阻塞到這個地方,所以現在針對IO密集型服務,異步才是最高效的方式。
該系統是一個io密集型的,基于有限狀態機的異步框架,同步的操作只有訪問mysql,redis這些都是異步訪問的,最終需要執行mysql的操作很少,而且mysql操作改成異步比較麻煩。所以排除鎖,先從cpu,內存等著手處理。
查看系統資源監控,cpu的idle長期處于70%,看來cpu的利用率不足,系統本身是多線程的,線程數可配置的,上調1.5倍的線程數,重啟觀察1天,發現沒有什么明顯的改善,還是有報警,cpu問題排除。
服務部署了2個機房,我比較了下兩個機房的配置,A機房的內存64G,cpu也好,B機房32G,cpu差點,A的流量比B的少很多,首先直接系統是無狀態的,修改下游的路由策略,改為不限定IDC,權重一致,使流量均勻,(我們內部有一套軟件,通過分布式路由控制可以做到),上線后A機房的報警明顯減少了,B機房由于流量增大,之前沒有的現在有了部分報警。問題看上去得到緩解。
后續上線了新的功能,這次會增加和下游服務多了一次udp通信,這次上線后,報警就多了,error數有時候到了100多,這下問題就需要繼續排查了。丟包,是因為接受的udp沒有及時處理。調低單個實例的權重,選一臺機器在上面部署兩個實例,上線觀察,恢復回去,問題又重新出現,通過比較發現,問題的確是系統處理速度太慢。看看內存占用,不到20多G,還很寬松,不是內存引起的, 網卡流量也還不到一般,網卡排除。
系統沒什么大的變化,難道是代碼新功能有耗時的地方,回滾了幾臺機器,觀察回滾了也沒啥效果。我也是沒啥頭緒,思考再三,先放著,暫時不影響業務。放置了幾天。晚上下班,想起來,同步操作除了mysql訪問,還有日志,我接手這個系統時,的確是逐漸加了一些日志。線上日志的level時INFO,再調高到WARN試下,上線后觀察,error不出現了。看來的確是log輸出影響了性能。問題目前來看得到了徹底的解決。但日志太少的問題,后續我們會有新的工具來實現分布式追蹤。
后續我又想了下,這個問題一開始我的思路也是錯了,這個系統本來規模就挺大,我自己首先就排除了業務增長導致的性能壓力,我接手了半年,半年里我司也是賣出了好幾千玩太手機,額每個手機都要連入我的服務,所以業務應該是的確增長一些,導致的性能壓力。很多時候,問題最后沒法解決,可能是自己把正確的解決方案先排除了。
由于半路轉的java后端,在這些問題排查方面經驗不足,特記錄一下,也算是一次經驗吧。