呼叫鏈系列(2):輕呼叫鏈實現

宜信技術學院發表於2019-08-14

一、前言

呼叫鏈系列(1):解讀UAVStack中的貪吃蛇

上篇文章分享了一下呼叫鏈的模型設計及模型時序圖。相信大家通過上一篇文章對呼叫鏈有了一個整體上的瞭解,如:呼叫鏈是什麼、能做什麼及整體實現策略。

這篇文章我們繼續介紹呼叫鏈的服務端資訊收集以及服務間上下文傳遞。

二、服務端資訊收集

服務端資訊收集整體流程如下圖所示,通過在應用容器(tomcat等)啟動過程中植入切點從而實現在應用邏輯執行之前和之後對請求進行劫持。

  • 應用邏輯執行之前:解析request中呼叫鏈資訊,並初始化呼叫鏈上下文;
  • 應用邏輯執行之後:解析response中呼叫鏈資訊,並將本次請求處理的所有呼叫鏈資訊輸出到日誌檔案。

三、切點植入

在介紹切點之前我們應該對servlet容器(本文以tomcat為例)處理一次請求的大致流程有一個整體的瞭解。

圖片來源於網路

在Connector接收到一次連線並轉化成請求(Request)後,會將請求傳遞到Engine的管道(Pipeline)的閥(ValveA)中。請求在Engine的管道中會傳遞到Engine Valve這個閥中。接著請求會從Engine Valve傳遞到一個Host的管道中,在該管道中傳遞到Host Valve這個閥裡。接著從Host Valve傳遞到一個Context的管道中,在該管道中傳遞到Context Valve中。接下來請求會傳遞到Wrapper C內的管道所包含的閥Wrapper Valve中,在這裡會經過一個過濾器鏈(Filter Chain),最終送到一個Servlet中。藉助於tomcat的這種架構設計,我們可以通過在tomcat處理一次請求的生命週期過程中植入自己的邏輯,將tomcat對外提供的能力進行一次增強,即UAV的中介軟體增強技術。

中介軟體增強技術除了巧妙運用了tomcat容器的架構設計之外還藉助了java Instrumentation(它給我們提供了一種能夠在物件第一次載入時動態修改位元組碼的能力,由於篇幅原因在此不進行詳細講解,不明白的小夥伴自行查閱資料)。在UAV中通過UAVServer對外提供各種切點能力。

有了中介軟體增強技術,在應用邏輯執行之前和之後的切點就有了,接下來就是在這些切點位置執行我們自己的呼叫鏈邏輯了。

四、中介軟體增強技術在呼叫鏈中的使用

上文介紹的間件增強技術是一種通過使用javaagent方式動態地在tomcat程式碼中植入切點程式碼並以UAVServer的形式對外提供能力的框架(具體能力後續文章會詳細介紹)。輕呼叫鏈實現正是使用了UAVServer對外提供的GlobalFilterHandler能力。

GlobalFilterHandler: 這裡的GlobalFilterHandler是中介軟體增強技術中的一種能力,與傳統的filter沒有任何關係。它對外提供了四個能力:

  • doRequest:在所有應用處理請求之前進行劫持;
  • doResponse:在所有應用處理請求之後進行劫持;
  • BlockHandlerChain:阻塞自當前handler以後的所有handler,此處的handler為註冊在當前;
  • BlockFilterChain阻塞自當前Filter以後的所有Filter。

呼叫鏈藉助於GlobalFilterHandler提供的前兩個能力,實現了在應用處理請求之前和之後執行呼叫鏈邏輯的功能。

五、輕呼叫鏈實現

具體UML圖如下:

從UML圖中可以清晰地看到, InvokeChainSupporter(呼叫鏈實現邏輯入口和呼叫鏈所需資源初始化實現類)將中介軟體增強技術進行了二次增強。它允許使用者在其中註冊不同的handler,並且在handler的preCap和doCap(中介軟體增強技術中的邏輯執行之前和之後的切點術語)方法之前和之後動態織入adapter,從而能夠執行更多的定製化適配和個性化邏輯。所有supporter和adapter均採用反射呼叫方式,最大程度上減少了中介軟體增強技術的依賴。

有了二次增強技術,我們就可以開始下面的呼叫鏈繪製工作了。

輕呼叫鏈繪製實現主要依賴於註冊在InvokeChainSupporter上的ServiceSpanInvokeChainHandler。主要繪製過程如下:

  • 解析請求資訊,提取其中呼叫鏈關心的資訊,並將解析出來的資訊放入上下文中;
  • 通過解析出來的請求頭資訊進行邏輯分流,根據不同的協議型別就行不同的邏輯處理; ✔mq邏輯 ✔http邏輯 ✔dubbo邏輯
  • 初始化呼叫鏈上下文,並初始化main span上下文;
  • 在應用處理完請求之後,將呼叫鏈資訊進行統一輸出。

下面來看一下具體每一步都做了什麼。

5.1 解析請求資訊

對於像tomcat這類中介軟體容器,所有進入tomcat的請求都會被封裝成HttpServletRequest和HttpServletResponse(後面簡稱request和response)最終進入使用者的servlet中。呼叫鏈藉助於中介軟體增強技術會在使用者邏輯處理之前將request和response進行一次攔截,並解析其中是否含有呼叫鏈資訊。如果有則將呼叫鏈資訊進行封裝放入上下文中。

5.2 邏輯分流

由於不同協議對應的呼叫鏈繪製邏輯也不同,此處呼叫鏈會根據協議型別進行一次分發。

5.3 初始化呼叫鏈上下文

將呼叫鏈上下文中的資訊進行解析:

  • 沒有父節點則將當前節點當作初始化節點,並初始化記錄當前服務內呼叫鏈資訊的main span;
  • 有父節點則根據父節點資訊初始化當前節點,並初始化記錄當前服務內呼叫鏈資訊的main span。

main span:在服務內可能會進行多次客戶端通訊或服務間通訊,需要一個main span來記錄當前服務內呼叫鏈最後一個節點的資訊。

5.4 呼叫鏈資訊輸出

在使用者邏輯處理結束之後,呼叫鏈記錄器會從上下文中取出當前服務的呼叫鏈資訊並將其輸出到指定日誌路徑。

5.5 服務間上下文傳遞

對於不同協議呼叫鏈傳遞資訊方式也略有不同,具體實現方式藉助了中介軟體增強技術提供的另一個能力:AppFrkHook(簡稱hook,此功能在客戶端呼叫鏈實現時會進行具體介紹)。它能夠對使用者使用的客戶端技術進行劫持,如使用者使用了httpclient進行通訊,則對httpclient進行劫持並動態織入程式碼,從而達到在http通訊的過程中注入呼叫鏈上下文資訊的效果。目標服務在解析請求資訊時,將呼叫鏈上下文進行解析;在初始化呼叫鏈上下文邏輯時,使用傳遞過來的資訊初始化目標服務的呼叫鏈上下文,實現跨系統呼叫時呼叫鏈連線。

六、總結

讀完本文之後讀者應該對中介軟體增強技術的實現有了一個大概的瞭解,並且對其提供的GlobalFilterHandler能力有了一定的認識。對於呼叫鏈應明白了服務端和服務間呼叫鏈的繪製全過程。

作者:李崇

來源:宜信技術學院


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69918724/viewspace-2653630/,如需轉載,請註明出處,否則將追究法律責任。

相關文章