dubbo源码解析之基础篇

410 阅读4分钟

dubbo架构

RPC调用链如下

服务消费方代理创建流程图
服务调用方流程图

更多架构请参考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();

}