中間件增強框架之InterceptFramework
一、前言
在智能運維中,應用服務所使用的組件及JAR包等相關信息非常重要,這些信息能夠清晰地描繪一個應用服務的骨架,我們稱這些信息為應用畫像。在UAVStack中,中間件增強框架(MOF)下的InterceptFramework可以在應用啟動過程中獲取畫像信息。本文主要介紹InterceptFramework的架構原理和在此基礎上實現的應用畫像數據采集與存儲。
二、整體架構
2.1 關鍵技術
2.2 關鍵類及功能
- Profile數據和客戶端監控指標主要通過InterceptSupport和hookProxy機制捕獲和監控。
- Profile也會安裝至DataObserver對象并暴露JMX/HTTP接口。
2.3 攔截之前的準備
- 在應用啟動的特定生命周期內改寫字節碼,植入特定的邏輯處理代碼進行攔截。
- 攔截框架對應的Supporter啟動,從配置文件中獲取應該裝載的Listener,構建InterceptSupport實例,把Listener添加到InterceptSupport實例中。
2.4 具體的攔截邏輯
在應用啟動過程中的特定生命周期,之前植入的代碼攔截邏輯開始執行InterceptSupport的doIntercept方法,遍歷已注冊的Listener監聽器。每個監聽器都繼承自InterceptEventListener類。不同的子Listener對相應類型的畫像采集處理:AppProfilingListener負責監聽所有服務畫像事件,AppFrkHookFactoryListener負責監聽客戶端畫像事件。
三、架構說明
- InterceptSupport:單例作為統一的Profile/Client hook捕獲入口點
- InterceptContext:捕獲上下文接口, 所有捕獲參數由Context封裝
- InterceptEventListener:事件劫持監聽器, 所有監聽器需繼承并注冊監聽
- AppProfilingListener:服務畫像監聽器, 監聽所有服務畫像事件
- AppFrkHookFactoryListener:客戶端畫像監聽代理
四、關鍵類說明
- StandardProfile:實現了Profile接口,是畫像數據抓取實現類,提供了doProfiling方法負責抓取行為和生成抓取結果;
- ProfileHandler:不同的抓取邏輯和抓取點的共同接口,實現不同的抓取邏輯;提供了抓取行為的doProfiling方法;
- StandardProfileRepository:存儲畫像數據抓取數據結構;
- DataObserver:暴露了JMX/HTTP接口數據;
- Profile實時監控在從AppProfilingListener類調用startProfiling時,將Profile對象安裝到DataObserver對象中;
- DataObserver提供JMX/HTTP服務,供后續抓取使用,其中Http服務注冊了HttpJEEProfileObserver,主要負責畫像數據的抓取服務;
- 各個Handler類具體處理抓取的各類數據。
五、畫像數據
畫像數據即靜態數據,是在進程啟動時即可得到的數據,包括操作系統相關的信息、程序相關的信息、程序啟動后相關的初始化信息。
畫像數據主要包括服務畫像、溯源感知畫像和客戶端畫像三部分,如上圖所示。以下分別從這三個方面介紹畫像采集:
5.1 服務畫像采集
服務畫像描述了服務本體的信息,包括應用唯一標識(AppID)、服務名(Service ID)、服務實例的URI、服務接口的URI、服務接口的元數據(類、方法、入參出參、注解、部署描述符)。
以Tomcat為例,應用的啟動過程需要經過StandardContext的start方法。我們可以在此方法的最后植入代碼邏輯進行攔截,通過攔截可以獲取到以下信息:
- 應用名、webworkdir(工作目錄)、servletcontext、contextpath、basepath(應用實際路徑)等容器上下文信息;
- 根據相應的技術規范(Servlet、JAXRS、JAXWS、Spring等)獲取畫像數據,主要包括:通過反射的方式獲取類和方法名以及出參入參信息、掃描注解類、獲取注解信息、解析部署描述符文件(web.xml等)信息。
服務畫像除了獲取以上信息外,還獲取應用的日志路徑和所用JAR包等信息。
5.2 溯源畫像采集
溯源畫像采集主要借助HTTP協議Header中的字段進行溯源,通過中間件劫持技術攔截Tomcat中StandardEngineValve的Invoke方法,獲取溯源數據。
收集的數據有以下幾種:
- Client Address:直連客戶端IP地址;
- X-Forwarded-For:如果存在,則為代理路由地址鏈,則直連客戶端為代理服務;
- Host:表明遠程主機甚至端口信息,如果直連客戶端是代理服務,則Host為代理IP地址和端口;
- User-Agent:代理描述,可用來區分瀏覽器還是程序客戶端,還可以提取很多瀏覽器終端信息;
- UAV-Client-Src:HTTP客戶端劫持加入的Header字段,用于UAV應用之間調用的擬合。
5.3 客戶端畫像采集
客戶端畫像通過對一系列常用中間件客戶端進行劫持實現,目前已支持同步/異步http、數據庫jdbc、redis(jedis,aredis,lettuce)、mongodb、rocketmq/rabbitmq/Kafka、ESClient等。
劫持通過javaassist字節碼改寫、動態代理等AOP技術,在客戶端調用代碼中嵌入特定處理邏輯,獲取調用相關的信息,如調用地址、調用協議、調用結果等。
畫像數據基于調用地址、訪問協議、調用結果的特征提取來確定目標服務。
1)調用地址:以類URI格式表示
- http/https服務(業務/代理服務):http://
- 關系型數據庫(數據源服務):jdbc:
- 非關系型數據庫或緩存(數據源服務):
- 消息隊列(消息服務):mq:
2)訪問協議:某種訪問動作。例如HTTP的POST、SQL插入、發送/訂閱消息、Redis的hgethashall、Mongo的Collection操作等。
3)訪問結果特征:服務的基礎棧類型、是否集群,例如Nginx、Tomcat、Apache等。
- 以ESClient為例,我們可以劫持TransportService的sendRequest方法,植入我們的攔截代碼邏輯。
與服務畫像不同的是,客戶端畫像發生在具體客戶端調用過程中,并非在應用的啟動環節。
六、畫像存儲結構
畫像存儲按以下結構分層存儲:
- StandardProfileRespository存儲某個應用的整個畫像;
- StandardProfileElement存儲某類組件畫像(服務端、客戶端、日志、jar等);
- ProfileElementInstance存儲某類組件當中的某一個組件畫像,以服務組件畫像為例,如:如組件JAXRS、Servlets各為一個ProfileElementInstance,但它們同屬于服務組件這一StandardProfileElement.
DataObserver提供了JMX和HTTP兩種模式來暴露接口畫像數據,這一點與實時數據類似,在我們MOF系列的兄弟篇《中間件增加框架之CaptureFramework》中已經詳細介紹過,在此處不再贅述。
開源地址:開源地址:https://github.com/uavorg
作者:李興勝
來源:宜信技術學院