作者 | 劉慕雨 中國工商銀行軟件開發中心雲計算實驗室
在信息系統建設方面,工商銀行一直積極探索,以開放的姿態借鑒行業先進經驗,旨在為客戶提供更優質的金融服務和用戶體驗。隨着分布式架構和雲計算平台在工行的廣泛應用,如何高效排查程序錯誤或性能瓶頸,是個棘手的問題。
為此,我們基於 Arthas 建設了在線診斷平台,在保護客戶信息安全的原則基礎上,對相關能力做了剪裁和整合,通過 Web 方式支持更復雜的交互場景,在實際線上問題分析中發揮關鍵作用。
工行在線診斷平台:
下面對工行在線診斷平台的建設做個階段性總結,分享一下我們的建設經驗、實際效果以及未來展望,也希望能給社區提供一個參考。
傳統方式排查問題的痛點
對於后端工程師,一旦線上程序邏輯出錯,問題排查如同破案,在分析研判時,問題現場的第一手信息是最珍貴的。開發人員很容易首先想到的就是閱讀日志,從海量的日志中尋找蛛絲馬跡,這就好比是對犯罪現場周邊的視頻監控錄像逐一回看,非常辛苦。如果問題現場的日志記錄缺失,就嘗試在本地重現問題並調試解決,本地難以重現的,只能再加日志,再部署,再重現,然后再查日志,效率較低。對於復雜一些的比如程序性能問題,如何定位性能瓶頸,一不小心又要回到加日志、部署、查日志、再加日志的老路,不僅效率不高,也破壞了問題現場。
JDK 提供的工具如 jps、jmap、jstat、jstack、jconsole 等,可以為工程師提供一些幫助。Linux 操作系統的命令,如 top、free、pidstat、vmstat、iostat 等,也是排查問題尤其是性能調優必不可少的工具。但直接使用這些工具,對工程師的個人技術能力和經驗要求較高。而且對企業來說,在生產環境直接通過命令行操作,是很敏感的行為。因此,如何在保證安全的基礎上,又能像調試本地程序一樣更便捷的排查分析,是個棘手的問題。
Arthas 的解決方案
2018 年我們在參加一次 Dubbo Meetup 上,聽了關於使用開源的 Arthas 工具排查 Dubbo 問題的分享。研究發現,Arthas 通過 JVM 的 Attach 機制,在不影響服務連續性的情況下,實時連接到目標進程,便於工程師在線排查問題。此外,Arthas 的字節碼增強框架,可以通過 Instrumentation 技術動態修改字節碼(需要 Java 虛擬機實現支持 retransformClasses),替換成新的 class,這就為在線調試提供了可能。
Arthas 原理圖:
比如,使用 watch 命令,實時觀測方法的調用情況;使用 jad 命令,把字節碼反編輯成 java 代碼;使用 redefine 命令,可以對代碼做熱更新,讓開發人員告別不停“加日志、部署、查日志、再加日志”的套娃時代。在 Arthas 剛推出沒多久,還提供了一個簡單的 Web Console 功能,實際是一個以 Websocket 訪問 Arthas 進程的方式,這也為我們后面建設在線診斷平台提供了思路。
落地使用上的困難
直接使用 Arthas 的命令行交互方式,不能滿足金融級運維要求,在落地使用上存在一些實際的問題:
-
信息安全問題:Arthas 可以通過命令行方式,直接觀測方法的入參、返回值,這就涉及到一些客戶敏感信息,直接在生產環境使用命令行操作顯然是不合適的。
-
學習成本問題:工具的安裝使用存在一定的學習成本,尤其是對於新員工來說。
-
多人協作問題:當多個開發者對同一個目標進程進行診斷時,可能存在沖突,例如,一個同學正在 watch 某個方法,另一個同學把這個方法 redefine 了,那么第一個同學 watch 到的其實是別人替換后的代碼的運行情況,這就像一個多線程訪問共享資源的線程安全問題。再比如兩個同學都在 attach 同一個進程,一個同學用完了,直接把 Arthas 進程 shutdown(關閉),而另一個還在使用的同學就突然不能用了。
-
資源占用問題:如果開發者忘記關閉 Arthas,Arthas 進程會占用一定的系統資源(如內存、CPU)。當然,Arthas 本身對資源開銷是有很多考慮的,比如 Arthas 使用自定義的類加載器加載自身的類,在關閉時將引用置空,這樣在下一次垃圾回收的時候,自定義類加載器加載的類就會被回收,從而避免對原有工程的影響。因此,我們認為 Arthas 應該在排查問題時使用,而不應該當作常規監控工具一直運行。
-
環境不統一問題:在不同的 Java 虛擬機實現安裝和使用 Arthas,可能會碰到一些奇怪的問題,比如用 Hotspot 虛擬機運行 Arthas 進程,而目標虛擬機是 J9 實現,attach 的時候可能會出錯。另一方面,生產環境雲上、雲下節點規模龐大,網絡訪問權限是嚴格控制的,開發人員想遠程連接目標進程,涉及到權限開通、版本管理、安裝程序下發等問題。
技術方案
我們設計了一套輕巧的架構,讓開發人員以 Web UI 的方式,便捷、直觀的使用各類在線診斷能力。那么我們是怎么做的呢?
1. 整體架構
整體架構大致分成在線診斷平台、在線診斷網關(后簡稱網關)、在線診斷進程三部分,通過一個網關集群統一代理對雲上、雲下節點的訪問,網關提供 Restful 接口給在線診斷平台(后簡稱平台)調用。一個接口可能組合了多個 Arthas 指令,也可能對指令的執行結果進行剪裁和修改,處理成 json 格式數據返回給平台做展示。
整體架構圖:
1)在線診斷平台
在線診斷平台是開發人員進行在線診斷的入口,平台通過 Web UI 的方式提供一站式在線診斷能力,支持復雜的交互場景。除了提供出色的用戶體驗,平台還解決了安裝卸載、多人協作、用戶鑒權、連接保持、操作審計等問題。
-
安裝卸載:根據用戶在平台輸入目標節點和進程信息,實現診斷程序的安裝和卸載,具體將在下一節介紹。
-
多人協作:當多個用戶同時診斷同一個進程時,對於存在沖突的功能,平台通過分布式鎖實現互斥,保障同一時刻只有一個用戶能使用,當然這么做的前提是平台在功能設計時考慮原子性。另外,當一個用戶試圖關閉一個其他用戶正在使用的連接時,也會被拒絕。
-
用戶鑒權:建立審批和黑白名單機制,基於 RBAC 模型,同時聯動 CMDB,對操作人員的權限進行嚴格管控,普通開發者需要被授權才可使用,各類診斷功能的使用權限也和用戶角色掛鈎,權限控制強度從生產環境到開發環境逐漸減弱。
-
連接保持:Arthas 一些命令比如 dashboard,提供了實時監控目標進程整體運行情況的功能,默認每 5 秒刷新一次。對於這樣的功能,平台的前端通過 websocket 與后端保持連接,后端內存中維護了一個目標對象和已連接用戶的對照關系,如果多個用戶同時監控某個目標對象,后端每次只會定時發送一次請求給網關。這么做的好處,是在保證了實時監控的同時,節約連接資源,避免了多人訪問時,到目標服務器的不必要的重復連接。此外,為了防止用戶忘記卸載診斷進程,對照關系也會同步到配置中心,當內存中某個目標對象對應的用戶全部下線時,會觸發一次檢查,如果發現配置中心中的用戶也已經全部下線,平台會自動發送 shutdown 請求給網關,卸載診斷進程。
-
操作審計:通過切面的方式,對用戶的各類操作進行記錄和存儲,達到審計的目的。
2)在線診斷網關
網關的作用,一是統一打通了到行內雲上、雲下環境的火牆;二是由於我們當時使用的 Arthas 版本還不支持 Restful 接口(最新版本已支持),返回報文都是文本的形式,網關側在這里會對文本進行解析,處理成 json 格式的結構數據,方便平台側做展示。歸納起來,網關的主要目的是統一代理對目標節點的訪問,同時封裝診斷能力,提供標准 json 結構數據的 Restful 接口給行內各平台訪問。網關在封裝診斷能力時,還會進行參數校驗、超時管理、數據脫敏、文本處理等工作。
-
參數校驗:網關需要對診斷命令的參數做合法性校驗,比如tt命令要控制最大觀測次數防止撐爆內存,保證使用安全。
-
超時管理:一些監聽類的命令,比如watch命令,如果一直監聽不到調用,需要設置超時時間,防止連接一直不被釋放。
-
數據脫敏:對於涉及客戶敏感信息的命令,網關會做數據脫敏,保障客戶信息安全,部分關鍵業務的敏感數據,網關側會做封閉禁止訪問。
-
文本處理:網關向 Arthas 進程發送指令后,收到的報文是文本形式,為了便於平台側展示,網關將非結構數據處理成結構數據,並對文本中的一些非關鍵數據進行剪裁。這里要注意因為 telnet 有個窗口大小的配置要適當調整,配置太小的話有可能導致文本不全。
3)在線診斷進程
也就是 Arthas 進程,需要考慮安裝、啟停、版本管理、網絡隔離等問題,具體做法在下一節詳細介紹。
2. 診斷過程詳解
工程師第一次對目標服務器進行診斷時,涉及安裝、啟動、使用、卸載等一系列步驟,如下圖所示:
1)診斷前准備
下圖是我們的安裝界面,當用戶授權通過后,即可填寫目標服務器信息開始安裝。如果是傳統虛擬機時,用戶需輸入虛擬機 ip 和目標進程關鍵字(如進程的 pid、進程的啟動類名、進程的 jar 名稱等);如果是容器,還需提供容易 id:
2)開始安裝
用戶點擊安裝后,會觸發一系列操作。首先在線診斷平台發送一個探活請求給網關,網關收到請求后相應的也發送一個空指令給目標節點。平台根據響應判斷,如果探活成功,則發送診斷請求開始診斷;否則發送安裝請求到行內指定的管理系統(傳統虛擬機/容器,后續簡稱通道)。
3)獲取安裝介質
以傳統虛擬機為例(如果是容器則把安裝介質下發到宿主機),通道去目標服務器指定目錄查找診斷程序的版本文件,如果獲取成功且版本是最新的,則通道直接執行啟動腳本。否則,通道會通知目標服務器從公共的文件服務器上,下載最新版本的安裝介質。
4)啟動診斷程序
安裝介質實際是一個壓縮包,包括安裝腳本、jar、版本文件等。安裝介質首次下載到目標服務器后,通道對其解壓並執行啟動腳本。我們修改了 Arthas 的啟動腳本,根據用戶輸入的進程關鍵字,找到目標進程,然后使用和目標進程相同的 jdk 版本,啟動診斷程序。注意,啟動時 Arthas 的 target-ip 參數被設置為網關地址,以隔離其他渠道訪問,默認值 127.0.0.1 表示只能本地訪問。
5)使用和卸載
診斷進程接收用戶診斷指令,開始診斷。使用完用戶可手工點擊卸載,銷毀診斷進程。
實際使用效果
這里舉幾個例子,看一下平台的實際使用效果。
1. 控制面板
基於 dashboard 命令,控制面板實時展示目標進程的整體運行情況,包括線程、jvm、操作系統等,每隔 10s 刷新一次,用戶也可選擇手動刷新。線程按 CPU 使用率取 TOP10,jvm 主要展示內存分布和 GC 情況:
點擊查詢更多可以查看詳情,比如監控 jvm 的內存及垃圾回收情況:
2. 線程清單
線程清單頁面按 CPU 使用率分頁展示所有線程,支持按線程狀態(如 RUNNABLE、BLOCKED)過濾,在控制面板頁面點擊查看更多,也可以直接跳到此頁面:
點擊某條記錄,跳轉到線程詳情,展示線程堆棧,在堆棧中選中一個方法,則可以直接進行方法觀測、方法追蹤、方法追溯、方法監控、反編譯等操作:
3. 方法監測
方法監測指的是對方法運行情況的監控和觀測,具體包括下面幾個功能。
1)方法觀測
支持對選中的堆棧中的方法進行觀測,也就是 watch 命令,這里以開發環境舉例(開發環境不做數據脫敏),可以實時捕獲方法的輸入、輸出、異常堆棧、執行耗時等,並且支持指定觀測次數、耗時限制等條件。比如我這里對 UserServiceImpl 類的 findUser 方法的調用情況進行觀測:
當方法拋異常時展示堆棧:
2)方法追蹤
方法追蹤指的是追蹤方法的調用棧,打印每個方法的執行耗時,基於 trace 命令實現,在排查性能問題時非常有用。看一下方法追蹤的界面,直接高亮標記出調用棧上耗時最久的方法,也支持配置過濾規則,過濾一些不關心的方法(比如 java 底層代碼)。在這個方法調用棧界面,又可以選中其中某個方法,進行觀測、追溯、監控等操作,不同的診斷能力之間都是打通的:
3)方法追溯
有時需要追溯方法被誰調用了,則可以使用方法追溯。比如這里通過方法追溯可以看到 Dubbo 的 Filter 處理鏈:
4)方法監控
有時我們需要對某個方法一段時間的執行情況進行觀測,這時可以使用方法監控功能。比如這里每隔 10 秒統計一次方法的執行次數、成功失敗次數、平均耗時、失敗率等指標:
4. 反編譯
當我們需要確認 Java 虛擬機加載的代碼情況時,比如你修改的代碼是否生效,我們在本地經常使用一些反編譯工具以達目的。jad 命令提供了在線反編譯能力,我們基於 jad 以界面的形式展示 Java 虛擬機加載的實際代碼,同時也會展示類加載器樹、類的路徑。比如這里對 findUser 方法的反編譯情況(不指定方法名的話,則對整個類反編譯),可以看到這個類屬於 springboot 項目,被 spring 的類加載器加載:
5. 其他能力
我們對其他的實用命令,也做了一些封裝和定制,比如 sc、sm、redefine、tt 等,這里就不一一介紹。此外,我們也將實時診斷能力和內部監控運維系統相整合,在排查問題時,可以通過直接跳轉的方式申請在線診斷權限,對目標進程做實時診斷。下圖是行內全鏈路跟蹤產品截圖,支持直接對問題鏈路關聯的節點進行診斷:
回顧與展望
簡要回顧一下前面提到的幾個困難和我們的解決方案:
-
學習成本問題:我們通過 Web UI 的方式降低學習成本,也提供了更復雜的交互場景和出色的用戶體驗。通過網關統一提供 Resful 接口提供結構數據,也更便於集成到企業內部其他運維平台。
-
多人協作問題:通過會話管理、互斥訪問、自動卸載等手段,解決多人協作問題。
-
信息安全問題:通過用戶鑒權、數據脫敏、操作審計、網絡隔離等手段,解決信息安全問題。
-
資源占用問題:通過自動卸載、減少連接、自定義類加載器(Arthas自帶)等手段,在充分性能測試基礎上,保障資源占用可控。
-
環境不統一問題:通過搭建網關集群,統一代理對雲上、雲下環境的訪問。采用一致的策略,統一管理雲上、雲下環境介質的版本、下發和安裝。
當前,工行在線診斷平台已在實際線上問題分析中持續發揮關鍵作用,Arthas 也越來越得到社區的關注和開發者的認可。Arthas 官方在新版本中已經支持了 Restful 接口,提供結構數據,也支持了更豐富的診斷命令,這跟我們的建設思路不謀而合。未來,我們將繼續積極參與社區建設,將工行的實踐經驗分享給大家。
Arthas 有獎征文正在進行中!
為了讓更多開發者開始用上 Arthas 這個 Java 診斷神器,今年 3 月 26 日,Arthas 社區聯合 JetBrains 推出 Arthas 有獎征文活動:聊聊這些年你和 Arthas 之間的那些事兒。活動已進行至第五期,點擊鏈接即可參與:http://alibabacloud.mikecrm.com/9khcRrs,歡迎大家踴躍投稿,參與即有可能獲獎!
“阿里巴巴雲原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的公眾號。”