dubbo原始碼解析之基礎篇

鄧橋發表於2018-10-14

dubbo架構

RPC呼叫鏈如下

dubbo原始碼解析之基礎篇
服務消費方代理建立流程圖
服務呼叫方流程圖

更多架構請參考dubbo官方開發者指南http://dubbo.apache.org/en-us/docs/dev/design.html

通過這個流程圖可以看到dubbo的呼叫鏈是非常複雜的,並且dubbo抽象了非常多的SPI介面,保證了dubbo的擴充套件性。讓dubbo是一個非常容易擴充套件的框架。

  • ProxyFactory SPI介面實現Invoker和服務介面和物件的相互轉換
  • Filter SPI介面實現Invoker呼叫鏈的攔截,自由的新增擴充套件邏輯
  • Invoker介面實現可以實現本地以及遠端service方法的呼叫
  • Cluster SPI介面可以實現從Invoker
  • Directory選擇Invoker來實現失敗重試策略
  • LoadBalance SPI介面可以實現從多個可用的Invoker中負載均衡策略
  • Registry SPI介面可以實現URL的註冊,查詢和訂閱,取消訂閱
  • Protocol SPI介面實現基於service呼叫的入參,呼叫對應網路通訊框架來建立遠端方法呼叫Invoker。
  • Directory介面實現RegistryDirectory通過Registry訂閱到服務提供方的List,根據每個提供方URL呼叫Protocol實現類建立Invoker, 實現根據遠端方法呼叫資訊Invocation資訊返回Invoker List

dubbo核心介面之 Invoker物件

dubbo裡面大部分方法的入參都是Invoker物件,是dubbo裡面最核心的介面

package com.alibaba.dubbo.rpc;

import com.alibaba.dubbo.common.Node;

/**
 * Invoker. (API/SPI, Prototype, ThreadSafe)
 * 
 * @see com.alibaba.dubbo.rpc.Protocol#refer(Class, com.alibaba.dubbo.common.URL)
 * @see com.alibaba.dubbo.rpc.InvokerListener
 * @see com.alibaba.dubbo.rpc.protocol.AbstractInvoker
 * @author william.liangf
 */
public interface Invoker<T> extends Node {

    /**
     * get service interface.
     * 
     * @return service interface.
     */
    Class<T> getInterface();

    /**
     * invoke.
     * 
     * @param invocation
     * @return result
     * @throws RpcException
     */
    Result invoke(Invocation invocation) throws RpcException;
}

import com.alibaba.dubbo.common.URL;

/**
 * Node. (API/SPI, Prototype, ThreadSafe)
 * 
 * @author william.liangf
 */
public interface Node {

    /**
     * get url.
     * 
     * @return url.
     */
    URL getUrl();
    
    /**
     * is available.
     * 
     * @return available.
     */
    boolean isAvailable();

    /**
     * destroy.
     */
    void destroy();

}
複製程式碼

dubbo的資料匯流排URL物件描述了請求的協議型別,請求引數資料,dubbo.xml裡面的配置引數資訊都會轉化為url物件用於整個呼叫鏈來傳遞配置資訊。

dubbo客戶端註冊到註冊中心的url例項 consumer://192.168.0.1/com.dq.test.xxxService?application=sita-crm-front&category=consumers&check=false&default.check=false&dubbo=2.8.4&group=crm-web&interface=com.dq.test.xxxService&pid=733&revision=0.0.1-SNAPSHOT&side=consumer&timeout=60000&timestamp=1537006745855

dubbo服務端註冊到註冊中心的url例項 dubbo://192.168.0.1:20880/xxxService?anyhost=true&application=crm-web&default.delay=-1&default.group=crm-web&default.timeout=10000&delay=-1&dubbo=2.8.4&generic=false&interface=xxxService&pid=610&revision=0.0.1-SNAPSHOT&side=provider&timestamp=1537005166465

Invocation物件的實現封裝了遠端呼叫的請求資料,預設的實現是RpcInvocation類

 public interface Invocation {

	/**
	 * get method name.
	 * 
	 * @serial
	 * @return method name.
	 */
	String getMethodName();

	/**
	 * get parameter types.
	 * 
	 * @serial
	 * @return parameter types.
	 */
	Class<?>[] getParameterTypes();

	/**
	 * get arguments.
	 * 
	 * @serial
	 * @return arguments.
	 */
	Object[] getArguments();

	/**
	 * get attachments.
	 * 
	 * @serial
	 * @return attachments.
	 */
	Map<String, String> getAttachments();
	
	/**
     * get attachment by key.
     * 
     * @serial
     * @return attachment value.
     */
	String getAttachment(String key);
	
	/**
     * get attachment by key with default value.
     * 
     * @serial
     * @return attachment value.
     */
	String getAttachment(String key, String defaultValue);

    /**
     * get the invoker in current context.
     * 
     * @transient
     * @return invoker.
     */
    Invoker<?> getInvoker();
}
複製程式碼

dubbo核心之Protocal

@SPI("dubbo")
public interface Protocol {
    
    /**
     * 獲取預設埠,當使用者沒有配置埠時使用。
     * 
     * @return 預設埠
     */
    int getDefaultPort();

    /**
     * 暴露遠端服務:<br>
     * 1. 協議在接收請求時,應記錄請求來源方地址資訊:RpcContext.getContext().setRemoteAddress();<br>
     * 2. export()必須是冪等的,也就是暴露同一個URL的Invoker兩次,和暴露一次沒有區別。<br>
     * 3. export()傳入的Invoker由框架實現並傳入,協議不需要關心。<br>
     * 
     * @param <T> 服務的型別
     * @param invoker 服務的執行體
     * @return exporter 暴露服務的引用,用於取消暴露
     * @throws RpcException 當暴露服務出錯時丟擲,比如埠已佔用
     */
    @Adaptive
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;

    /**
     * 引用遠端服務:<br>
     * 1. 當使用者呼叫refer()所返回的Invoker物件的invoke()方法時,協議需相應執行同URL遠端export()傳入的Invoker物件的invoke()方法。<br>
     * 2. refer()返回的Invoker由協議實現,協議通常需要在此Invoker中傳送遠端請求。<br>
     * 3. 當url中有設定check=false時,連線失敗不能丟擲異常,並內部自動恢復。<br>
     * 
     * @param <T> 服務的型別
     * @param type 服務的型別
     * @param url 遠端服務的URL地址
     * @return invoker 服務的本地代理
     * @throws RpcException 當連線服務提供方失敗時丟擲
     */
    @Adaptive
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;

    /**
     * 釋放協議:<br>
     * 1. 取消該協議所有已經暴露和引用的服務。<br>
     * 2. 釋放協議所佔用的所有資源,比如連線和埠。<br>
     * 3. 協議在釋放後,依然能暴露和引用新的服務。<br>
     */
    void destroy();

}
複製程式碼

相關文章