摘要:遠程調用本地調用目標介紹本地調用的設計和實現,介紹的源碼。前言是一個遠程調用的框架,但是它沒有理由不支持本地調用,本文就要講解關于本地調用的實現。服務暴露者集合取消暴露調用父類的取消暴露方法從集合中移除二該類繼承了類,是本地調用的實現。
遠程調用——injvm本地調用
目標:介紹injvm本地調用的設計和實現,介紹dubbo-rpc-injvm的源碼。前言
dubbo是一個遠程調用的框架,但是它沒有理由不支持本地調用,本文就要講解dubbo關于本地調用的實現。本地調用要比遠程調用簡單的多。
源碼分析 (一)InjvmExporter該類繼承了AbstractExporter,是本地服務的暴露者封裝,其中實現比較簡單。只是實現了unexport方法,并且維護了一份保存暴露者的集合。
class InjvmExporter(二)InjvmInvokerextends AbstractExporter { /** * 服務key */ private final String key; /** * 暴露者集合 */ private final Map > exporterMap; InjvmExporter(Invoker invoker, String key, Map > exporterMap) { super(invoker); this.key = key; this.exporterMap = exporterMap; exporterMap.put(key, this); } /** * 取消暴露 */ @Override public void unexport() { // 調用父類的取消暴露方法 super.unexport(); // 從集合中移除 exporterMap.remove(key); } }
該類繼承了AbstractInvoker類,是本地調用的invoker實現。
class InjvmInvokerextends AbstractInvoker { /** * 服務key */ private final String key; /** * 暴露者集合 */ private final Map > exporterMap; InjvmInvoker(Class type, URL url, String key, Map > exporterMap) { super(type, url); this.key = key; this.exporterMap = exporterMap; } /** * 服務是否活躍 * @return */ @Override public boolean isAvailable() { InjvmExporter> exporter = (InjvmExporter>) exporterMap.get(key); if (exporter == null) { return false; } else { return super.isAvailable(); } } /** * invoke方法 * @param invocation * @return * @throws Throwable */ @Override public Result doInvoke(Invocation invocation) throws Throwable { // 獲得暴露者 Exporter> exporter = InjvmProtocol.getExporter(exporterMap, getUrl()); // 如果為空,則拋出異常 if (exporter == null) { throw new RpcException("Service [" + key + "] not found."); } // 設置遠程地址為127.0.0.1 RpcContext.getContext().setRemoteAddress(NetUtils.LOCALHOST, 0); // 調用下一個調用鏈 return exporter.getInvoker().invoke(invocation); } }
其中重寫了isAvailable和doInvoke方法。
(三)InjvmProtocol該類是本地調用的協議實現,其中實現了服務調用和服務暴露方法,并且封裝了一個判斷是否是本地調用的方法。
1.屬性/** * 本地調用 Protocol的實現類key */ public static final String NAME = Constants.LOCAL_PROTOCOL; /** * 默認端口 */ public static final int DEFAULT_PORT = 0; /** * 單例 */ private static InjvmProtocol INSTANCE;2.getExporter
static Exporter> getExporter(Map> map, URL key) { Exporter> result = null; // 如果服務key不是* if (!key.getServiceKey().contains("*")) { // 直接從集合中取出 result = map.get(key.getServiceKey()); } else { // 如果 map不為空,則遍歷暴露者,來找到對應的exporter if (map != null && !map.isEmpty()) { for (Exporter> exporter : map.values()) { // 如果是服務key if (UrlUtils.isServiceKeyMatch(key, exporter.getInvoker().getUrl())) { // 賦值 result = exporter; break; } } } } // 如果沒有找到exporter if (result == null) { // 則返回null return null; } else if (ProtocolUtils.isGeneric( result.getInvoker().getUrl().getParameter(Constants.GENERIC_KEY))) { // 如果是泛化調用,則返回null return null; } else { return result; } }
該方法是獲得相關的暴露者。
3.export@Override public4.referExporter export(Invoker invoker) throws RpcException { // 創建InjvmExporter 并且返回 return new InjvmExporter (invoker, invoker.getUrl().getServiceKey(), exporterMap); }
@Override public5.isInjvmReferInvoker refer(Class serviceType, URL url) throws RpcException { // 創建InjvmInvoker 并且返回 return new InjvmInvoker (serviceType, url, url.getServiceKey(), exporterMap); }
public boolean isInjvmRefer(URL url) { final boolean isJvmRefer; // 獲得scope配置 String scope = url.getParameter(Constants.SCOPE_KEY); // Since injvm protocol is configured explicitly, we don"t need to set any extra flag, use normal refer process. if (Constants.LOCAL_PROTOCOL.toString().equals(url.getProtocol())) { // 如果是injvm,則不是本地調用 isJvmRefer = false; } else if (Constants.SCOPE_LOCAL.equals(scope) || (url.getParameter("injvm", false))) { // if it"s declared as local reference // "scope=local" is equivalent to "injvm=true", injvm will be deprecated in the future release // 如果它被聲明為本地引用 scope = local"相當于"injvm = true",將在以后的版本中棄用injvm isJvmRefer = true; } else if (Constants.SCOPE_REMOTE.equals(scope)) { // it"s declared as remote reference // 如果被聲明為遠程調用 isJvmRefer = false; } else if (url.getParameter(Constants.GENERIC_KEY, false)) { // generic invocation is not local reference // 泛化的調用不是本地調用 isJvmRefer = false; } else if (getExporter(exporterMap, url) != null) { // by default, go through local reference if there"s the service exposed locally // 默認情況下,如果本地暴露服務,請通過本地引用 isJvmRefer = true; } else { isJvmRefer = false; } return isJvmRefer; }
該方法是判斷是否為本地調用。
后記該部分相關的源碼解析地址:https://github.com/CrazyHZM/i...
該文章講解了遠程調用中關于injvm本地調用的部分,三種抽象的角色還是比較鮮明的,服務暴露相關的exporter、服務引用相關的invoker、以及協議相關的protocol,關鍵還是弄清楚再設計上的意圖,以及他們分別代表的是什么。那么看這些不同的協議實現會很容易看懂。接下來我將開始對rpc模塊關于memcached協議部分進行講解。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73232.html
摘要:大揭秘異步化改造目標從源碼的角度分析的新特性中對于異步化的改造原理。看源碼解析四十六消費端發送請求過程講到的十四的,在以前的邏輯會直接在方法中根據配置區分同步異步單向調用。改為關于可以參考源碼解析十遠程通信層的六。 2.7大揭秘——異步化改造 目標:從源碼的角度分析2.7的新特性中對于異步化的改造原理。 前言 dubbo中提供了很多類型的協議,關于協議的系列可以查看下面的文章: du...
摘要:服務暴露過程目標從源碼的角度分析服務暴露過程。導出服務,包含暴露服務到本地,和暴露服務到遠程兩個過程。其中服務暴露的第八步已經沒有了。將泛化調用版本號或者等信息加入獲得服務暴露地址和端口號,利用內數據組裝成。 dubbo服務暴露過程 目標:從源碼的角度分析服務暴露過程。 前言 本來這一篇一個寫異步化改造的內容,但是最近我一直在想,某一部分的優化改造該怎么去撰寫才能更加的讓讀者理解。我覺...
摘要:前言基于表單的遠程調用協議,采用的實現,關于協議就不用多說了吧。后記該部分相關的源碼解析地址該文章講解了遠程調用中關于協議的部分,內容比較簡單,可以參考著官方文檔了解一下。 遠程調用——http協議 目標:介紹遠程調用中跟http協議相關的設計和實現,介紹dubbo-rpc-http的源碼。 前言 基于HTTP表單的遠程調用協議,采用 Spring 的HttpInvoker實現,關于h...
摘要:而存在的意義就是保證請求或響應對象可在線程池中被解碼,解碼完成后,就會分發到的。 2.7大揭秘——服務端處理請求過程 目標:從源碼的角度分析服務端接收到請求后的一系列操作,最終把客戶端需要的值返回。 前言 上一篇講到了消費端發送請求的過程,該篇就要將服務端處理請求的過程。也就是當服務端收到請求數據包后的一系列處理以及如何返回最終結果。我們也知道消費端在發送請求的時候已經做了編碼,所以我...
摘要:可以參考源碼解析二十四遠程調用協議的八。十六的該類也是用了適配器模式,該類主要的作用就是增加了心跳功能,可以參考源碼解析十遠程通信層的四。二十的可以參考源碼解析十七遠程通信的一。 2.7大揭秘——消費端發送請求過程 目標:從源碼的角度分析一個服務方法調用經歷怎么樣的磨難以后到達服務端。 前言 前一篇文章講到的是引用服務的過程,引用服務無非就是創建出一個代理。供消費者調用服務的相關方法。...
閱讀 1074·2021-11-16 11:45
閱讀 2708·2021-09-27 13:59
閱讀 1315·2021-08-31 09:38
閱讀 3143·2019-08-30 15:52
閱讀 1315·2019-08-29 13:46
閱讀 2085·2019-08-29 11:23
閱讀 1631·2019-08-26 13:47
閱讀 2476·2019-08-26 11:54