dubbo原始碼之服務呼叫過程

2021-10-10 00:22:52 字數 4114 閱讀 1961

前面有介紹服務暴露和服務引入兩個流程,而這兩個流程就是為了服務的呼叫。由前面兩篇可以知道我們具體呼叫資訊已經被封裝到invoker 裡面。今天主要是介紹dubbo在呼叫服務的時候,如何獲取到封裝好invoker,對服務進行呼叫。

這篇文章和前面三篇一樣,基於dubbo 2.7.1、 zookeeper為註冊中心、採用dubbo 協議。

由前面服務引入可以知道呼叫介面,是dubbo controller 進行屬性賦值的時候注入**物件。

可以看到注入**是來自invokerinvocationhandler 的**物件,invokerinvocationhandler 裡面封裝了mockclusterinvoker 物件。

可以看到前面主要是獲取一些引數,就由mockclusterinvoker 物件進行具體呼叫了

public result invoke(invocation invocation) throws rpcexception 

result = this.domockinvoke(invocation, (rpcexception)null);

} else catch (rpcexception var5)

if (logger.iswarnenabled())

result = this.domockinvoke(invocation, var5);}}

} else

return result;

}

mock 的話就不展開分析了,我們來看看 this.invoker.invoke 的實現,實際上會呼叫 abstractclusterinvoker#invoker

public result invoke(invocation invocation) throws rpcexception 

//裡面呼叫的是this.directory.list(invocation); 裡面做路由過濾

list> invokers = this.list(invocation);

//過濾完初始化負載均衡器

loadbalance loadbalance = this.initloadbalance(invokers, invocation);

rpcutils.attachinvocationidifasync(this.geturl(), invocation);

//預設呼叫子類failoverclusterinvoker #doinvoker

return this.doinvoke(invocation, invokers, loadbalance);

}//初始化負載均衡器

protected loadbalance initloadbalance(list> invokers, invocation invocation)

failoverclusterinvoker #doinvoker 的呼叫方法,在這個方法中進行重試容錯處理

public result doinvoke(invocation invocation, list> invokers, loadbalance loadbalance) throws rpcexception 

rpcexception le = null;

list> invoked = new arraylist(invokers.size());

setproviders = new hashset(len);

for(int i = 0; i < len; ++i)

//根據上乙個類abstractclusterinvoker 中獲取到負載均衡方式,獲取到乙個合適invoker

invokerinvoker = this.select(loadbalance, invocation, copyinvokers, invoked);

invoked.add(invoker);

//儲存上下文呼叫過資訊,下次重試過濾用

rpccontext.getcontext().setinvokers(invoked);

try

result var13 = result;

return var13;

} catch (rpcexception var18)

le = var18;

} catch (throwable var19) finally

}throw new rpcexception(le.getcode(), "failed to invoke the method " + methodname + " in the service " + this.getinte***ce().getname() + ". tried " + len + " times of the providers " + providers + " (" + providers.size() + "/" + copyinvokers.size() + ") from the registry " + this.directory.geturl().getaddress() + " on the consumer " + netutils.getlocalhost() + " using the dubbo version " + version.getversion() + ". last error is: " + le.getmessage(), (throwable)(le.getcause() != null ? le.getcause() : le));}}

invoker.invoke(invocation);過程中會經過挺多過濾器、介面卡,我們直接跳過看abstractinvoker的 invoke方法。這個是跳過過濾器類。

abstractinvoker呼叫this.doinvoke(invocation);的子類dubboinvoker#

doinvoke方法

protected result doinvoke(invocation invocation) throws throwable  else 

try else if (isasync) else

return (result)result;

} else

} catch (timeoutexception var12) catch (remotingexception var13)

}

oneway,就是當你不關心你的請求是否傳送成功的情況下,就用 oneway 的方式傳送,這種方式消耗最小,啥都不用記,啥都不用管。

非同步呼叫,其實 dubbo 天然就是非同步的,可以看到 client 傳送請求之後會得到乙個 responsefuture,然後把 future 包裝一下塞到上下文中,這樣使用者就可以從上下文中拿到這個 future,然後使用者可以做了一波操作之後再呼叫 future.get 等待結果。

同步呼叫,這是我們最常用的,也就是 dubbo 框架幫助我們非同步轉同步了,從**可以看到在 dubbo 原始碼中就呼叫了 future.get,所以給使用者的感覺就是我呼叫了這個介面的方法之後就阻塞住了,必須要等待結果到了之後才能返回,所以就是同步的。

到這裡就將dubbo 訊息傳送給服務提供者了

首先客戶端呼叫介面的某個方法,實際呼叫的是invokerinvocationhandler **類,**類會通過 cluster 從 directory 中獲取 invokers列表,然後進行 router 的過濾,然後再通過 spi 得到 loadbalance 進行一波負載均衡。

預設的 cluster 是 failovercluster ,根據獲取到負載均衡器選擇invoker 進行呼叫,如果呼叫失敗進行容錯重試處理,

在呼叫過程中,根據設定具體的協議構造請求頭,然後將引數根據具體的序列化協議序列化之後構造塞入請求體中,再通過 nettyclient 發起遠端呼叫。

dubbo 原始碼分析 服務呼叫過程 三

dubbo 遠端服務呼叫過程 為了便於理解,分析前所看一下整個架構及相關元件說明 這裡直接看官方文件就了,介紹非常清晰 整體架構說明 集群容錯 分析原始碼前,必須貼一張官方的呼叫煉圖 為了方便分析服務集群路由,負載均衡,建議開多個幾服務提供方 接著上一編的 始 public class invoke...

Dubbo服務呼叫過程

生產者,服務提供者 提供端 消費者,服務呼叫者 呼叫端 provider,服務提供者 container,容器 spring容器,用來初始化服務 服務發布,需要spring容器配合 服務註冊 registry,註冊中心 生產者,暴露服務 註冊到註冊中心 查詢服務 消費者,訪問註冊中心 返回訊息 註冊...

Dubbo呼叫過程監控

monitorfilter 主要對呼叫過程進行監控,public result invoke invoker invoker,invocation invocation throws rpcexception catch rpcexception e finally else 其核心 是 colle...