業務系統請求zabbix圖表性能調優
性能調優實踐
背景
用 vue.js 的框架 ant-design vue pro 實現的一個監控系統,後端用第三方開源組件 zabbix 提供監控數據採集,前端的展示中一個頁面會同時請求 N 個圖表,頁面響應時間很慢,極端情況下甚至達到 10s , 用戶體驗很差,所以領導給了個小任務,優化整個頁面的請求響應。
領導發現頁面響應很慢,說了一句:「這些圖表顯示這麼慢,應該一開始就想著優化的」,這裡我覺得這個觀點有待商榷,最近在讀《重構》這本書,裡面的一個觀點我很認同:「做任何事情,先做出來,再優化」,這是一個應用面很廣的策略,跟 Linux 的哲學之一「單個程式負責一個小功能」的組織模式,都有廣泛用法;當工期有限的情況下,先把東西做出來(這裡不光指代程式,而是任何產品或者其他交付物),再考慮優化它,因為有了產出物才會有後續的東西,而且任何人不可能一開始就把所有的情況和變化的需求考慮得面面俱到。Linux 哲學裡的那句話同樣可以用於人員組織、社會分工合作方面,專人專事,讓專業人士來做(比如:黑人抬棺),效率不言而喻。
顯示很慢的圖如下:
問題分析
之前從來沒有做過性能優化和分析,這次從零開始優化,需要自己認真分析排查,這個頁面會請求同一個介面,不獲取不同監控指標的圖表數據,大概 10-20 個圖表渲染,在排查之前想到可能的性能瓶頸:
- 前端頁面優化不好(前端用的 axios.all 來發送多個並發請求,頁面會在所有後端響應後才渲染,可能瓶頸在這裡)
- 後端介面的並發沒有優化過,可能性能瓶頸在這裡
- zabbix 這個開源中間件的響應時間過慢,負載過高
- mysql 資料庫引擎沒有優化,造成性能過低
後端優化排查
作為全棧開發者,首先想到的是從後端服務開始優化,而沒有優化經驗怎麼入手,當然是先找輪子了,Google 找了一下工具,有如下可用:
- 阿里的 Arthas java診斷工具
- OneAPM(鏈路追蹤,類似於 skywalking 之類的工具,甚至可以監測我的 springboot項目)
- Oracle 的 Java Mission Control
- 淘寶的Tprofiler、Jprofiler
- MyBatis-Plus 性能分析插件(這裡我的後端是 springboot + Mybatis-Plus , 這個插件可以幫助我分析 SQL 慢查詢,列印出所有的查詢語句)
詢問了下同事,發現大家也沒什麼優化經驗,所以我選用了之前了解了一點的 Arthas 工具作為診斷。
進入 Arthas 的官網,可以用它的在線教程快速入門(它是一個沙盒的 linux 環境,能夠快速掌握 Arthas 的基礎使用和概念),然後,知道使用方法後,把 Arthas 的 jar 包放到我的 centos 線上測試環境中(Arthas 本身也支援 windows 的,可以本地調試)
java -jar arthas-boot.jar
然後用 trace 命令來追蹤某個方法調用鏈路上的耗時
trace xxxx.xxx xxx
此時,我們請求前端程式碼,就能在後台看到對這個調用方法的每一步的耗時了
此時,我們就可以去具體的程式碼分析耗時原因了,重複 trace 可以進一步精確定位哪個方法開銷最大。
Arthas 還有很多非常強大的功能,對於 java 程式設計師非常友好,建議自行探索:
發現介面響應時間為 500 ms 後,感覺性能瓶頸可能不在後端(當然,這裡肯定還有一定的優化空間,但是不是主要矛盾)
前端優化排查
發現後端介面響應時長沒有那麼誇張之後,把目光放到了前端上來,F12 打開了 chrome 瀏覽器的開發者工具後,發現幾個問題:
- 同一個介面並發了很多次
- Stalled 和 Waiting(TTFB)很長
繼續 Google ,搜索 同時發送多個請求造成 chrome stalled 時長過大(當然用英文關鍵詞搜索),果然在 stackoverflow 發現了這個問題的解答,[//stackoverflow.com/questions/27513994/chrome-stalls-when-making-multiple-requests-to-same-resource],裡面提到了幾種解決方式:
- 給 response header 增加
Cache-Control: no-cache, no-store
,這個我在後端增加後沒有效果,這裡別人討論的是瀏覽器的快取機製造成請求過慢 - 給我們的請求 url 後面增加一個隨機數,比如
?ran='+Math.random()
,讓請求不一致,達到欺騙瀏覽器,讓它每次都發送一個新的請求,這個實驗後也不能讓響應時間變短
此時的我陷入了沉思,問題究竟處在哪裡?同事提醒我一個規律,超過 6 個請求後,後面的都會開始有一串灰色的長耗時(就是我們看到的 stalled),另外一個同事說好像是 jquery 的限制還是怎樣,繼續搜索,發現這個是 瀏覽器對同一個域名的多並發請求個數的限制,參考博文:
發現了這個限制之後,我們把圖表的請求個數限制在6個以內,跟之前相比頁面渲染速度確實有明顯提升,規避了請求數量過多造成 stalled 的問題,當然,這個只是一種解決方案,v2ex 上的同學有很多其他可參考的解決方式。
參考騰訊的藍鯨監控里的圖表繪製,它們採取了分頁請求控制數量,盡量給客戶展示少的圖表,同時提供每頁顯示更多的選擇(每頁 4 個圖表秒開,8個的時候就開始有 loading 的效果了)
解決了前端超過 6 個請求的阻塞問題,問題到了有的請求 Waiting(TTFB)很長上來了,這又是個什麼呢?搜索一番發現,這個是服務端的響應(看來後端還是很有優化空間的,參考博文:ttfb是什麼)
後端長響應排查
這個圖表請求介面有的會特別慢,甚至有的會 2-3 秒,定位到問題出在跟三方組件 zabbix-server 的請求交互上,這是非常需要優化的,打開我們的 fiddle 抓包工具看請求:
fiddle 使用小技巧
控制面板-Internet 選項-連接-區域網設置-代理伺服器(不勾選為 LAN 使用代理伺服器)
設置地程式碼的代理埠為 8888 (fiddle 默認使用的就是 8888)
這樣設置後,fiddle 就只會抓取我本地 idea 發送的請求了,過濾掉了瀏覽器里的干擾請求。
用 Fiddler 抓 Postman的模擬請求
每個圖表請求分三個:
- 登錄 zabbix 獲取 token
- 請求監控項
- 根據監控項獲取圖表
參考 zabbix 的官方文檔,做了程式碼層面的優化:
- 出於性能考慮,快取 token ,避免每次都登錄請求一個新 token
- 檢索監控項只檢索你需要的屬性(這一點比較好理解,zabbix 服務端我們用的 mysql 引擎,相當於只查詢特定的欄位,跟全表查性能肯定不一樣)
後端優化還包括:用特定的監控項取代發現類型監控項(這個是發現磁碟介面過慢的原因,會發現 70 多個文件目錄),請求某個主機的所有發現類型監控項寫到我們的業務庫(只請求一次)等;
zabbix server 優化
單個後端請求的瓶頸在於我們用 zabbix api 去請求 zabbix server 所返回的過程,所以,對zabbix server 本身的優化也是整個鏈路的重要方面。參考 zabbix 的官方文檔後,有這樣一些方面:
-
歷史數據保存時間儘可能的小,這樣資料庫不會超負荷運行,查詢的效率也更高
[//www.zabbix.com/documentation/4.0/zh/manual/config/items/history_and_trends] -
調優zabbix的資料庫引擎,這個是調優最重要的部分(由於沒有 dba ,本人對資料庫調優也不懂,這個暫時無法做到,搜索了下我們使用的 mysql 5.6 使用的是 InnoDB 引擎)
[//www.zabbix.com/documentation/4.0/zh/manual/appendix/performance_tuning]
對於 zabbix 本身優化官方文檔還沒整個看一遍,等全部找一遍說不定能找到進一步壓榨性能的方法~
總結
此次優化涉及了很多方面,前端、後端、伺服器等,優化後的用戶體驗得到了提升,也遇到了一些坑,不斷提高自己解決問題的能力,才是程式設計師的價值,共勉!