什麼是Dubbo的上下文信息?這裏總結下本身的理解:java
上下文中存放的是當前 調用過程中所需的環境信息。全部的配置信息都將轉換成URL的參數。RpcContext類就是Dubbo的上下文,可是它僅僅是一個ThreadLocal級別的 臨時狀態記錄器,當接收到RPC請求或發起RPC請求時,RpcContext的狀態都會變化。好比:A調用B、B再調用C的狀況下。 B機器的RpcContext會有以下的狀況發生:在B調用C以前,RpcContext記錄的是A調B的信息,在B調用C以後,RpcContext記錄的是B調C的信息。
好比:咱們想要獲取到服務調用者的host相關信息,那麼咱們能夠在服務提供者中獲取當前消費此服務的消費者的host信息,其代碼以下所示:spring
// 獲取調用方的host信息 String serverIP = RpcContext.getContext().getRemoteHost();
舉個例子:用戶在執行下單這個業務,最終確定會通過後臺的訂單服務、庫存服務等服務。如今有個需求:在訂單服務中,要明確知道這個訂單是哪一個用戶建立的。在庫存服務中,要明確知道這個商品最終是用戶的哪一個操做致使減小的。整個需求裏面有個核心:就是要知道操做者是誰!假設項目用的是jwt技術來記錄用戶的狀態,那麼訂單服務和庫存服務就必需要知道這個jwt字符串,將jwt解碼後,就能知道當前請求是由哪一個用戶發起的。在這樣的一個場景中,使用dubbo的隱式參數能夠達到上述的目的。實現的僞代碼以下所示:apache
RpcContext.getContext().setAttachment("jwt", "xxxxxxxxxxjwt字符串xxxxxxxx"); // dubbo rpc 調用庫存服務:減小庫存 warehouseService.decrement(); // dubbo rpc 調用訂單服務:建立訂單 orderService.create();
這裏先總結下attachment在使用上的幾個特色:框架
一、key名稱不能以小駝峯命名,下游服務序列化後,會將key名稱變成全小寫(Dubbo 2.6.x版本,在2.7.x版本被修復了)分佈式
二、隱式參數設置後,僅在第一次RPC請求生效,後續的RPC請求將沒法獲取到隱式參數學習
由於attachment有上述的兩個特色,所以咱們很容易以下的兩個錯誤:測試
易犯錯誤1 | 易犯錯誤2 |
---|---|
咱們在warehouseService.decrement() 的下游服務中能順利的從attachment中獲取jwt參數,而在orderService.create() 的下游服務中已經沒法順利的從attachment中獲取jwt參數了 |
在本例中,添加到attachment中的key爲jwt,是ok的。但若是咱們把key設置成大駝峯的命名方式,好比:userJwt。在通過Dubbo的一系列處理後,在warehouseService.decrement() 下游服務中的rpcContext對象中的attachment中的key已經變成了userjwt,已經沒法獲取到key爲jwt的參數了。 |
針對錯誤1,咱們有三個實現方案,其對應的方案策略以下所示:編碼
方案 | 優勢 | 缺點 |
---|---|---|
方案1:在每一次發起RPC以前,都手動執行一次RpcContext.getContext().setAttachment("jwt", "xxxxxxxxxxjwt字符串xxxxxxxx"); 代碼 |
能解決問題,但不是最優方案 | 增長編碼的複雜度和代碼的重複度。 |
方案2:使用spring的aop 的before機制,在執行rpc發起遠程服務以前,先把jwt放入到attachment中 | 能解決問題 | dubbo的遠程調用對象自己就很重量,如今再添加一層代理,不利於定位問題。 |
方案3:使用Dubbo的filter機制,在對指定遠程服務添加一層filter,filter的邏輯就是將jwt放入到attachment中去 | 比較好的一種解決方案,充分利用到了Dubbo框架自身提供的filter擴展。這也是比較通用的解決方案,全鏈路追蹤的traceId也是這麼玩的。(推薦) | 代碼閱讀性不高,filter同aop同樣,都是解耦的,不利於定位問題。 |
針對錯誤2,在不對源碼進行擴展的狀況下,最簡單的方式就是修改key的命名方式,這裏可使用兩種方式:spa
方式1 | 參考Dubbo源碼的org.apache.dubbo.common.constants.CommonConstants類中對添加到URL中的key的命令方式,多個單詞用. 作區分 |
---|---|
方式2 | 單詞與單詞間使用自定義的符號作分隔,好比_,# 等符號。這種方式也能夠區分於key是本身添加的仍是Dubbo框架自帶的。 |