前言
Dubbo源碼閱讀分享系列文章,歡迎大家關注點贊
SPI實現部分
註冊中心
通信
RPC
整體介紹
Dubbo的RPC其實是對Protocol的封裝,整體的結構與Remoting類似,dubbo-rpc-api是對具體協議、服務暴露、服務引用、代理等的抽象,是整個RPC中的核心,其他模塊是對該層具體的實現,每個模塊都是Dubbo具體支持的協議。
dubbo-rpc-api
dubbo-rpc-api整體模塊如圖所示,整體接口包括了filter、listener、protocol、proxy、support以及核心API,接下來我們先來看下核心的接口介紹。
核心接口
開始之前我們來先來回顧一下之前介紹RPC請求的過程,
Rpc Client通過傳入的IP、端口號、調用類以及方法的參數,通過動態代理找到具體的調用類的方法,將請求的類、方法序列化,傳輸到服務端; 當Rpc Service收到請求以後,將傳入類和方法反序列化,通過反射找到對應的類的方法進行調用,最後將返回結果進行序列化,返回客戶端; Rpc Client收到返回值以後,進行反序列化,最後將結果展示;
這裏爲什麼要回顧整個過程,這樣後面介紹抽象的接口的時候大家會更更容易理解爲什麼這麼抽象。
Invoker
Invoker接口內部有三個方法,分別是getInterface、invoke、destroyAll,getInterface該方法主要是獲取服務接口相關的信息,invoke主要是發起一次調用以及相應信息,destroyAll主要用於銷燬調用請求。
public interface Invoker<T> extends Node {
//獲取服務接口
Class<T> getInterface();
//發起調用
Result invoke(Invocation invocation) throws RpcException;
//銷燬調用連接
default void destroyAll() {
destroy();
}
}
Invocation
Invocation是invoke的參數,內部抽象了RPC調用的目標服務、方法信息、相關參數信息、具體的參數值以及一些附加信息。
public interface Invocation {
//調用Service的唯一標識
String getTargetServiceUniqueName();
String getProtocolServiceKey();
//調用的方法名稱
String getMethodName();
//服務名稱
String getServiceName();
//參數類型集合
Class<?>[] getParameterTypes();
//參數簽名集合
default String[] getCompatibleParamSignatures() {
return Stream.of(getParameterTypes())
.map(Class::getName)
.toArray(String[]::new);
}
//調用具體的參數值
Object[] getArguments();
//調用關聯的Invoker對象
Map<String, String> getAttachments();
@Experimental("Experiment api for supporting Object transmission")
Map<String, Object> getObjectAttachments();
void setAttachment(String key, String value);
@Experimental("Experiment api for supporting Object transmission")
void setAttachment(String key, Object value);
@Experimental("Experiment api for supporting Object transmission")
void setObjectAttachment(String key, Object value);
void setAttachmentIfAbsent(String key, String value);
@Experimental("Experiment api for supporting Object transmission")
void setAttachmentIfAbsent(String key, Object value);
@Experimental("Experiment api for supporting Object transmission")
void setObjectAttachmentIfAbsent(String key, Object value);
/**
* get attachment by key.
*
* @return attachment value.
* @serial
*/
String getAttachment(String key);
@Experimental("Experiment api for supporting Object transmission")
Object getObjectAttachment(String key);
/**
* get attachment by key with default value.
*
* @return attachment value.
* @serial
*/
String getAttachment(String key, String defaultValue);
@Experimental("Experiment api for supporting Object transmission")
Object getObjectAttachment(String key, Object defaultValue);
/**
* get the invoker in current context.
*
* @return invoker.
* @transient
*/
Invoker<?> getInvoker();
//Invoker對象可以設置一些KV屬性,這些屬性並不會傳遞給Provider
Object put(Object key, Object value);
Object get(Object key);
Map<Object, Object> getAttributes();
}
Result
Result接口是Invoker.invoke方法的返回值,該返回值包含了被調用方返回值(或是異常)以及附加信息,我們也可以添加回調方法,在 RPC 調用方法結束時會觸發這些回調。
public interface Result extends Serializable {
//調用的返回值
Object getValue();
void setValue(Object value);
//異常處理方法
Throwable getException();
void setException(Throwable t);
boolean hasException();
//複合操作,如果調用發生異常,則直接拋出異常,如果沒有異常,則返回結果
Object recreate() throws Throwable;
//攜帶附加信息
Map<String, String> getAttachments();
@Experimental("Experiment api for supporting Object transmission")
Map<String, Object> getObjectAttachments();
void addAttachments(Map<String, String> map);
@Experimental("Experiment api for supporting Object transmission")
void addObjectAttachments(Map<String, Object> map);
void setAttachments(Map<String, String> map);
@Experimental("Experiment api for supporting Object transmission")
void setObjectAttachments(Map<String, Object> map);
String getAttachment(String key);
@Experimental("Experiment api for supporting Object transmission")
Object getObjectAttachment(String key);
String getAttachment(String key, String defaultValue);
@Experimental("Experiment api for supporting Object transmission")
Object getObjectAttachment(String key, Object defaultValue);
void setAttachment(String key, String value);
@Experimental("Experiment api for supporting Object transmission")
void setAttachment(String key, Object value);
@Experimental("Experiment api for supporting Object transmission")
void setObjectAttachment(String key, Object value);
//添加回調 當RPC調用完成時,會觸發回調
Result whenCompleteWithContext(BiConsumer<Result, Throwable> fn);
<U> CompletableFuture<U> thenApply(Function<Result, ? extends U> fn);
//阻塞線程,等待此次RPC調用完成
Result get() throws InterruptedException, ExecutionException;
Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
Exporter
Exporter暴露Invoker的實現,就是讓Provider能夠根據請求的各種信息,找到對應的Invoker的實現。
public interface Exporter<T> {
//獲取Invoker對象
Invoker<T> getInvoker();
//取消Invoker對象
void unexport();
}
Protocol
Protocol接口主要有三個核心方法export、refer以及destroy,export主要是將Invoker服務暴露出去,refer引用一個服務將Invoker對象返回,destroy主要是銷燬Invoker,釋放Protocol對底層的佔用。Protocol接口的實現中,export方法並不是簡單地將Invoker對象包裝成Exporter對象返回,其中還涉及代理對象的創建、底層Server的啓動等操作;refer方法除了根據傳入的type類型以及URL參數查詢Invoker之外,還涉及相關Client的創建等操作。 此外該接口被SPI修飾,export和refer被Adaptive修飾,因此對於Protocol可以動態選擇實現,此外Dubbo也提供多種Protocol實現。
@SPI("dubbo")
public interface Protocol {
//默認端口
int getDefaultPort();
//將一個Invoker暴露,該方法必須是冪等的
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
//引用一個Invoker,返回一個Invoker對象
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
//銷燬export方法以及refer方法使用到的Invoker對象,釋放當前Protocol對象底層佔用的資源
void destroy();
//返回當前Protocol底層的全部ProtocolServer
default List<ProtocolServer> getServers() {
return Collections.emptyList();
}
}
Filter
Filter接口用來攔截Dubbo請求,定義了一個invoke方法將請求傳遞給後續的Invoker進行處理。
@SPI
public interface Filter {
//將請求傳給後續的Invoker處理
Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException;
//監聽響應以及異常
interface Listener {
void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation);
void onError(Throwable t, Invoker<?> invoker, Invocation invocation);
}
}
ProxyFactory
ProxyFactory接口主要的功能是用來創建代理對象,此外ProxyFactory也是一個擴展接口,getProxy方法爲Invoker創建代理對象,getInvoker方法將代理對象轉爲Invoker對象,默認採用javassist生成代理對象,Dubbo還提供很多種實現,可以通過SPI配置進行自定義。
@SPI("javassist")
public interface ProxyFactory {
//將Invoker對象轉爲代理對象
@Adaptive({PROXY_KEY})
<T> T getProxy(Invoker<T> invoker) throws RpcException;
@Adaptive({PROXY_KEY})
<T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException;
//將proxy對象轉爲Invoker
@Adaptive({PROXY_KEY})
<T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
}
結束
歡迎大家點點關注,點點贊!