dubbo源码

dubbo源码构建参考
官方文档
在这里插入图片描述
Provider: 暴露服务的服务提供方
Protocol 负责提供者和消费者之间协议交互数据
Service 真实的业务服务信息 可以理解成接口 和 实现
Container Dubbo的运行环境
Consumer: 调用远程服务的服务消费方
Protocol 负责提供者和消费者之间协议交互数据
Cluster 感知提供者端的列表信息
Proxy 可以理解成 提供者的服务调用代理类 由它接管 Consumer中的接口调用逻辑
Registry: 注册中心,用于作为服务发现和路由配置等工作,提供者和消费者都会在这里进行注册
Monitor: 用于提供者和消费者中的数据统计,比如调用频次,成功失败次数等信息。

启动和执行的流程如上图
提供者端启动 容器负责把Service信息加载 并通过Protocol 注册到注册中心
消费者端启动 通过监听提供者列表来感知提供者信息 并在提供者发生改变时 通过注册中心及时 通知消费端
消费方发起请求 通过Proxy模块
利用Cluster模块 来选择真实的要发送给的提供者信息
交由Consumer中的Protocol 把信息发送给提供者
提供者同样需要通过 Protocol 模块来处理消费者的信息
最后由真正的服务提供者 Service 来进行处理

在这里插入图片描述
调用链路
淡绿色代表了 服务生产者的范围 淡蓝色 代表了服务消费者的范围 红色箭头代表了调用的方向

  1. 消费者通过Interface进行方法调用 统一交由消费者端的 Proxy 通过ProxyFactory 来进行代理 对象的创建 使用到了 jdk javassist技术
  2. 交给Filter 这个模块 做一个统一的过滤请求
  3. 接下来会进入最主要的Invoker调用逻辑
    通过Directory 去配置中新读取信息 最终通过list方法获取所有的Invoker
    通过Cluster模块 根据选择的具体路由规则 来选取Invoker列表
    通过LoadBalance模块 根据负载均衡策略 选择一个具体的Invoker 来处理我们的请求
    如果执行中出现错误 并且Consumer阶段配置了重试机制 则会重新尝试执行
  4. 继续经过Filter 进行执行功能的前后封装 Invoker 选择具体的执行协议
  5. 客户端 进行编码和序列化 然后发送数据
  6. 到达Provider中的 Server 在这里进行 反编码 和 反序列化的接收数据
  7. 使用Exporter选择执行器
  8. 交给Filter 进行一个提供者端的过滤 到达 Invoker 执行器
  9. 通过Invoker 调用接口的具体实现 然后返回

在这里插入图片描述
Business 业务逻辑层
service 业务层 包括我们的业务代码 比如 接口 实现类 直接面向开发者

RPC层 远程过程调用层
config 配置层 对外提供配置 以ServiceConfig ReferenceConfig 为核心 可以直接初始化配置 类 也可以解析配置文件生成
proxy 服务代理层 无论是生产者 还是消费者 框架都会产生一个代理类 整个过程对上层透明 就是 业务层对远程调用无感
registry 注册中心层 封装服务地址的注册与发现 以服务的URL为中心
cluster 路由层 (集群容错层) 提供了多个提供者的路由和负载均衡 并且它桥接注册中心 以Invoker为核心
monitor 监控层 RPC调用相关的信息 如 调用次数 成功失败的情况 调用时间等 在这一层完成
protocol 远程调用层 封装RPC调用 无论是服务的暴露 还是 服务的引用 都是在Protocol中作为主 功能入口 负责Invoker的整个生命周期 Dubbo中所有的模型都向Invoker靠拢

Remoting层 远程数据传输层
exchange 信息交换层 封装请求和响应的模式 如把请求由同步 转换成异步
transport 网络传输层 统一网络传输的接口 比如 netty 和 mina 统一为一个网络传输接口
serialize 数据序列化层 负责管理整个框架中的数据传输的序列化 和反序列化

当dubbo启动后会在zookeeper下生成一个dubbo的子目录,dubbo下面是当前的接口名称
在这里插入图片描述
接口下面的四格配置项是
consumers: 当前服务下面所有的消费者列表(URL)
providers: 当前服务下面所有的提供者列表(URL)
configuration: 当前服务下面的配置信息信息,provider或者consumer会通过读取这里的配 置信息来获取配置
routers: 当消费者在进行获取提供者的时,会通过这里配置好的路由来进行适配匹配规则。
可以看到,dubbo基本上很多时候都是通过URL的形式来进行交互获取数据的,在URL中也会保存 很多的信息

服务的注册过程分析

    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.test.service.HelloService"    ref="helloService"/>
    <!-- 和本地bean一样实现服务 -->
    <bean id="helloService" class="com.test.service.impl.HelloServiceImpl" />

dubbo在这里的配置会被解析成ServiceConfig,启动的时候会调用doExportUrlsFor1Protocol方法

private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
//省略。。。
	//ref是实际提供服务的class,interfaceClass是提供服务的接口
	//在这里通过PROXY_FACTORY(JavassistProxyFactory)生成一个invoker
	Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
	DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);	
	//从这里把服务提供方的地址等信息注册到zookeeper
	//protocol=RegistryProtocol
    Exporter<?> exporter = protocol.export(wrapperInvoker);
    exporters.add(exporter);
//省略。。。
}       

进入RegistryProtocol的export方法

 @Override
    public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
        //...
        //获取当前url是否需要进行注册参数
        boolean register = providerUrl.getParameter(REGISTER_KEY, true);
        if (register) {
        	//注册
            register(registryUrl, registeredProviderUrl);
        }
        // 对override协议进行注册,用于在接收到override请求时做适配,这种方式用于适配2.6.x及之 前的版本(混用)
        registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
		// 设置当前导出中的相关信息
        exporter.setRegisterUrl(registeredProviderUrl);
        exporter.setSubscribeUrl(overrideSubscribeUrl);
        // 返回导出对象(对数据进行封装)
        return new DestroyableExporter<>(exporter);
    }
public void register(URL registryUrl, URL registeredProviderUrl) {
		//获得注册中心
        Registry registry = registryFactory.getRegistry(registryUrl);
        //注册  调用ListenerRegistryWrapper的register方法
        registry.register(registeredProviderUrl);
		// ProviderModel 表示服务提供者模型,此对象中存储了与服务提供者相关的信息。 
		// 比如服务的配置信息,服务实例等。每个被导出的服务对应一个 ProviderModel。
        ProviderModel model = ApplicationModel.getProviderModel(registeredProviderUrl.getServiceKey());
        model.addStatedUrl(new ProviderModel.RegisterStatedURL(
                registeredProviderUrl,
                registryUrl,
                true
        ));
    }

调用org.apache.dubbo.registry.ListenerRegistryWrapper#register

public void register(URL url) {
        try {
        	//进入FailbackRegistry的register方法
            registry.register(url);
        }
 	//...
}
@Override
    public void register(URL url) {
        if (!acceptable(url)) {
            logger.info("URL " + url + " will not be registered to Registry. Registry " + url + " does not accept service of this protocol type.");
            return;
        }
        // 上层调用
		// 主要用于保存已经注册的地址列表
        super.register(url);
        // 将一些错误的信息移除(确保当前地址可以在出现一些错误的地址时可以被删除)
        removeFailedRegistered(url);
        removeFailedUnregistered(url);
        try {
            //开始注册
            doRegister(url);
        } catch (Exception e) {
            Throwable t = e;

            // 记录日志
            boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)
                    && url.getParameter(Constants.CHECK_KEY, true)
                    && !CONSUMER_PROTOCOL.equals(url.getProtocol());
            boolean skipFailback = t instanceof SkipFailbackWrapperException;
            if (check || skipFailback) {
                if (skipFailback) {
                    t = t.getCause();
                }
                throw new IllegalStateException("Failed to register " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t);
            } else {
                logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t);
            }

            // 后台异步进行重试
            addFailedRegistered(url);
        }
    }

进入org.apache.dubbo.registry.zookeeper.ZookeeperRegistry#doRegister

@Override
    public void doRegister(URL url) {
        try {
        	//按dubbo/接口名/provider生成path 注册到zk
            zkClient.create(toUrlPath(url), url.getParameter(DYNAMIC_KEY, true));
        } catch (Throwable e) {
            throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }

url规则
url地址格式为 protocol://host:port/path?key=value&key=value

provider://192.168.20.1:20883/com.test.service.HelloService? anyhost=true&application=service- provider2&bind.ip=192.168.20.1&bind.port=20883&category=configurators&check=fals e&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.test.service

URL主要有以下几部分组成:
protocol: 协议,一般像我们的 provider 或者 consumer 在这里都是人为具体的协议
host: 当前 provider 或者其他协议所具体针对的地址,比较特殊的像 override 协议所指定的 host就是 0.0.0.0 代表所有的机器都生效
port: 和上面相同,代表所处理的端口号
path: 服务路径,在 provider 或者 consumer 等其他中代表着我们真实的业务接口
key=value: 这些则代表具体的参数,这里我们可以理解为对这个地址的配置。比如我们 provider 中需要具体机器的服务应用名,就可以是一个配置的方式设置上去。
注意:Dubbo中的URL与java中的URL是有一些区别的,如下:
这里提供了针对于参数的 parameter 的增加和减少(支持动态更改)
提供缓存功能,对一些基础的数据做缓存.

服务本地缓存

在ZookeeperRegistry的父类AbstractRegistry中

public AbstractRegistry(URL url) {
    setUrl(url);
    // Start file save timer
	syncSaveFile = url.getParameter(REGISTRY_FILESAVE_SYNC_KEY, false);
	// 默认保存路径(home/.dubbo/dubbo-registry-appName-address-port.cache) String defaultFilename = System.getProperty("user.home") + "/.dubbo/dubbo-
	registry-" + url.getParameter(APPLICATION_KEY) + "-" + url.getAddress().replaceAll(":", "-") + ".cache";
	String filename = url.getParameter(FILE_KEY, defaultFilename); // 创建文件
	File file = null;
	if (ConfigUtils.isNotEmpty(filename)) {
	    file = new File(filename);
		if (!file.exists() && file.getParentFile() != null && !file.getParentFile().exists()) {
			if (!file.getParentFile().mkdirs()) {
				throw new IllegalArgumentException("Invalid registry cache file" + file + ", cause: Failed to create directory " + file.getParentFile() + "!"); 
			}
		} 
	}
	this.file = file;
	// 加载已有的配置文件 
	loadProperties(); 
	notify(url.getBackupUrls());
}

跟一下notify(url.getBackupUrls());最后会进入saveProperties(url)方法

private void saveProperties(URL url) {
    if (file==null) {
		return; 
	}
	try {
	StringBuilder buf = new StringBuilder();
	// 获取所有通知到的地址
	Map<String, List<URL>> categoryNotified = notified.get(url);
    if (categoryNotified != null) {
        for (List<URL> us : categoryNotified.values()) {
            for (URL u : us) {
            	//多个地址拼接
                if (buf.length() > 0) {
                    buf.append(URL_SEPARATOR);
                }
                buf.append(u.toFullString());
            }
        }
    }
	// 保存数据
	properties.setProperty(url.getServiceKey(), buf.toString());
	// 保存为一个新的版本号
	// 通过这种机制可以保证后面保存的记录,在重试的时候,不会重试之前的版本 
	long version = lastCacheChanged.incrementAndGet();
	// 需要同步保存则进行保存
	if (syncSaveFile) {
	    doSaveProperties(version);
	} else {
	// 否则则异步去进行处理
		registryCacheExecutor.execute(new SaveProperties(version)); }
	} catch (Throwable t) { 
		logger.warn(t.getMessage(), t);
	} 
}
public void doSaveProperties(long version) {
        if (version < lastCacheChanged.get()) {
            return;
        }
        if (file == null) {
            return;
        }
        // Save
        try {
        	// 使用文件级别所,来保证同一段时间只会有一个线程进行读取操作
            File lockfile = new File(file.getAbsolutePath() + ".lock");
            if (!lockfile.exists()) {
                lockfile.createNewFile();
            }
            try (RandomAccessFile raf = new RandomAccessFile(lockfile, "rw");
                 FileChannel channel = raf.getChannel()) {
                 // 利用文件锁来保证并发的执行的情况下,只会有一个线程执行成功(原因在于可能是跨VM的)
                FileLock lock = channel.tryLock();
                if (lock == null) {
                    throw new IOException("Can not lock the registry cache file " + file.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties");
                }
                // Save
                try {
                    if (!file.exists()) {
                        file.createNewFile();
                    }
                    // 将配置的文件信息保存到文件中
                    try (FileOutputStream outputFile = new FileOutputStream(file)) {
                        properties.store(outputFile, "Dubbo Registry Cache");
                    }
                } finally {
                	// 解开文件锁
                    lock.release();
                }
            }
        } catch (Throwable e) {
        	// 执行出现错误时,则交给专门的线程去进行重试
            savePropertiesRetryTimes.incrementAndGet();
            if (savePropertiesRetryTimes.get() >= MAX_RETRY_TIMES_SAVE_PROPERTIES) {
                logger.warn("Failed to save registry cache file after retrying " + MAX_RETRY_TIMES_SAVE_PROPERTIES + " times, cause: " + e.getMessage(), e);
                savePropertiesRetryTimes.set(0);
                return;
            }
            if (version < lastCacheChanged.get()) {
                savePropertiesRetryTimes.set(0);
                return;
            } else {
                registryCacheExecutor.execute(new SaveProperties(lastCacheChanged.incrementAndGet()));
            }
            logger.warn("Failed to save registry cache file, will retry, cause: " + e.getMessage(), e);
        }
    }

dubbo消费过程

在ReferenceConfig中的init方法生成代理

public synchronized void init() {
	//省略。。
	ref = createProxy(map);
	//省略。。
}
private T createProxy(Map<String, String> map) {
	//获得一个invoker
	invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
	//生成一个invoker的远程服务代理
	return (T) PROXY_FACTORY.getProxy(invoker);
}

invoker中有配置信息

<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:application name="service-consumer"     >
         <dubbo:parameter key="qos.enable" value="true" ></dubbo:parameter>
         <dubbo:parameter key="qos.port" value="33333"></dubbo:parameter>
         <dubbo:parameter key="qos.accept.foreign.ip" value="true" ></dubbo:parameter>
    </dubbo:application>
    <!--    -->
    <dubbo:consumer timeout="2000"   check="false" ></dubbo:consumer>

    <!-- 使用zookeeper注册中心暴露发现服务地址 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2182"  timeout="10000"/>

    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="helloService"  interface="com.test.service.HelloService"  timeout="4000" retries="2"/>

Dubbo扩展SPI源码

ExtensionLoader是所有Dubbo中SPI的入口
org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader 方法:获取扩展点加载器 并加载所对应的所有的扩展点实现
org.apache.dubbo.common.extension.ExtensionLoader.getExtension 方法:根据name 获取扩展的指定实现

 public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
        // 必须传入类型
        if (type == null) {
            throw new IllegalArgumentException("Extension type == null");
        }
        // 必须是接口类型
        if (!type.isInterface()) {
            throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
        }
        // 必须有@SPI
        if (!withExtensionAnnotation(type)) {
            throw new IllegalArgumentException("Extension type (" + type +
                    ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
        }
        // 尝试从缓存中加载
        ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        if (loader == null) {
            // 如果没有才进行初始化   并且放入缓存中
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
            loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        }
        return loader;
    }
private ExtensionLoader(Class<?> type) {
        this.type = type;
        // 创建ExtensionFactory 对象   ExtensionFactory 也是一个扩展点
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }
/**
 * ExtensionFactory
 *  根据传入的扩展点类型  和  名字  来获取扩展  这里和我们SPI中的具体名称实现挂钩
 */
@SPI
public interface ExtensionFactory {
    /**
     * Get extension.
     *
     * @param type object type.
     * @param name object name.
     * @return object instance.
     */
    <T> T getExtension(Class<T> type, String name);
}

它有两个实现(版本不同实现类可能不一样)
在这里插入图片描述

@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

    private final List<ExtensionFactory> factories;

    public AdaptiveExtensionFactory() {
        // 获取针对 ExtensionFactory 的扩展加载器
        ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
        List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
        // 获取支持的扩展
        for (String name : loader.getSupportedExtensions()) {
            // 对扩展进行缓存
            list.add(loader.getExtension(name));
        }
        factories = Collections.unmodifiableList(list);
    }

    @Override
    public <T> T getExtension(Class<T> type, String name) {
        // 交给真实的扩展来处理   用ExtensionFactory的实现类的getExtension方法来获取type的实现
        for (ExtensionFactory factory : factories) {
            T extension = factory.getExtension(type, name);
            if (extension != null) {
                return extension;
            }
        }
        return null;
    }

}

进入org.apache.dubbo.common.extension.ExtensionLoader#getSupportedExtensions

public Set<String> getSupportedExtensions() {
      // 扩展类的信息  name 和 Class 对应
      Map<String, Class<?>> clazzes = getExtensionClasses();
      // 获取扩展点的名字
      return Collections.unmodifiableSet(new TreeSet<>(clazzes.keySet()));
}
private Map<String, Class<?>> getExtensionClasses() {
        // 从缓存中获取已经加载的扩展类
        Map<String, Class<?>> classes = cachedClasses.get();
        // 双重检查
        if (classes == null) {
            // 为空就锁住
            synchronized (cachedClasses) {
                // 防止重复加载
                classes = cachedClasses.get();
                if (classes == null) {
                    // 加载扩展类信息  并缓存
                    classes = loadExtensionClasses();
                    cachedClasses.set(classes);
                }
            }
        }
        return classes;
    }
private Map<String, Class<?>> loadExtensionClasses() {
        // 加载默认的扩展实现
        cacheDefaultExtensionName();

        Map<String, Class<?>> extensionClasses = new HashMap<>();
        // 获取每个目录下  名称和实现类对应的关系
        for (LoadingStrategy strategy : strategies) {
            loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
            loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
        }

        return extensionClasses;
    }

进入org.apache.dubbo.common.extension.ExtensionLoader#cacheDefaultExtensionName方法

private void cacheDefaultExtensionName() {
        // 如果没有@SPI  则返回
        final SPI defaultAnnotation = type.getAnnotation(SPI.class);
        if (defaultAnnotation == null) {
            return;
        }
        // 获取默认的扩展名
        // 比如LoadBalance  默认实现是random
        String value = defaultAnnotation.value();
        if ((value = value.trim()).length() > 0) {
            String[] names = NAME_SEPARATOR.split(value);
            if (names.length > 1) {
                throw new IllegalStateException("More than 1 default extension name on extension " + type.getName()
                        + ": " + Arrays.toString(names));
            }
            if (names.length == 1) {
                cachedDefaultName = names[0];
            }
        }
    }

回到org.apache.dubbo.common.extension.ExtensionLoader#loadDirectory()方法

private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
                               boolean extensionLoaderClassLoaderFirst, String... excludedPackages) {
       // 路径 + 包名.接口名
        String fileName = dir + type;
        try {
            Enumeration<java.net.URL> urls = null;
            ClassLoader classLoader = findClassLoader();
            
            // try to load from ExtensionLoader's ClassLoader first
            if (extensionLoaderClassLoaderFirst) {
                ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
                if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) {
                    urls = extensionLoaderClassLoader.getResources(fileName);
                }
            }
            
            if(urls == null || !urls.hasMoreElements()) {
                if (classLoader != null) {
                    urls = classLoader.getResources(fileName);
                } else {
                    urls = ClassLoader.getSystemResources(fileName);
                }
            }
             // 遍历每一个资源文件,并且进行加载资源信息到extensionClasses(缓存), 主要功能是读取文件内容
            if (urls != null) {
                while (urls.hasMoreElements()) {
                    java.net.URL resourceURL = urls.nextElement();
                    //读取资源文件并加载class
                    loadResource(extensionClasses, classLoader, resourceURL, excludedPackages);
                }
            }
        } catch (Throwable t) {
            logger.error("Exception occurred when loading extension class (interface: " +
                    type + ", description file: " + fileName + ").", t);
        }
    }
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
                              java.net.URL resourceURL, String... excludedPackages) {
        try {
            // 根据resourceURL 读取文件
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    // # 后面是注释  读取#前面的内容
                    final int ci = line.indexOf('#');
                    if (ci >= 0) {
                        line = line.substring(0, ci);
                    }
                    line = line.trim();
                    if (line.length() > 0) {
                        try {
                            String name = null;
                            int i = line.indexOf('=');
                            if (i > 0) {
                                // 加载  key = value 形式的数据
                                name = line.substring(0, i).trim();
                                line = line.substring(i + 1).trim();
                            }
                            if (line.length() > 0 && !isExcluded(line, excludedPackages)) {
                                // 对类信息进行加载操作
                                loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
                            }
                        } catch (Throwable t) {
                            IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
                            exceptions.put(line, e);
                        }
                    }
                }
            }
        } catch (Throwable t) {
            logger.error("Exception occurred when loading extension class (interface: " +
                    type + ", class file: " + resourceURL + ") in " + resourceURL, t);
        }
    }
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
        // 当前扩展点 必须是接口的实现
        if (!type.isAssignableFrom(clazz)) {
            throw new IllegalStateException("Error occurred when loading extension class (interface: " +
                    type + ", class line: " + clazz.getName() + "), class "
                    + clazz.getName() + " is not subtype of interface.");
        }
        // 如果包含了 @Adaptive  就存储到cacheAdaptiveClass
        if (clazz.isAnnotationPresent(Adaptive.class)) {
            cacheAdaptiveClass(clazz);
        } else if (isWrapperClass(clazz)) {
            // 判断是否是wrapper类型, 是否构造函数中有该接口类型的传入
            // wrapper类型的意思是,对当前的扩展点实现封装功能处理
            cacheWrapperClass(clazz);
        } else {
            clazz.getConstructor();
            // 看是否已经定义过name  如果定义过就是一之前的  否则就是当前的简单名称
            if (StringUtils.isEmpty(name)) {
                name = findAnnotationName(clazz);
                if (name.length() == 0) {
                    throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
                }
            }
            //  对name 和 class  做映射
            String[] names = NAME_SEPARATOR.split(name);
            if (ArrayUtils.isNotEmpty(names)) {
                // 如果当前类 有Activate  标注  则加入到 cacheActivateClass 中  意味着需要执行
                cacheActivateClass(clazz, names[0]);
                for (String n : names) {
                    // 进行名称映射保存
                    cacheName(clazz, n);
                    saveInExtensionClass(extensionClasses, clazz, n);
                }
            }
        }
    }

在loadclass方法中会判断是否更新这几个值
cachedAdaptiveClass: 当前Extension类型对应的AdaptiveExtension类型(只能一个)
cachedWrapperClasses: 当前Extension类型对应的所有Wrapper实现类型(无顺序)
cachedActivates: 当前Extension实现自动激活实现缓存(map,无序)
cachedNames: 扩展点实现类对应的名称(如配置多个名称则值为第一个)

根据name获取扩展点的方法 getExtension

public T getExtension(String name) {
        if (StringUtils.isEmpty(name)) {
            throw new IllegalArgumentException("Extension name == null");
        }
        // 获取当前SPi的默认扩展实现类
        if ("true".equals(name)) {
            return getDefaultExtension();
        }
        // 获取当前类的Holder   建立一个引用 判断 加锁
        final Holder<Object> holder = getOrCreateHolder(name);
        Object instance = holder.get();
        if (instance == null) {
            synchronized (holder) {
                instance = holder.get();
                if (instance == null) {
                    instance = createExtension(name);
                    holder.set(instance);
                }
            }
        }
        return (T) instance;
    }
	private Holder<Object> getOrCreateHolder(String name) {
        // 根据当前名称 从缓存中获取 holder
        Holder<Object> holder = cachedInstances.get(name);
        if (holder == null) {
            // 如果不存在 则创建一个 放入缓存
            cachedInstances.putIfAbsent(name, new Holder<>());
            holder = cachedInstances.get(name);
        }
        return holder;
    }
    private T createExtension(String name) {
        // 从 getExtensionClasses() 中来根据name 获取对应的Class对象
        Class<?> clazz = getExtensionClasses().get(name);
        if (clazz == null) {
            throw findException(name);
        }
        try {
            // 获取实例
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
                // 如果不存在扩展实例 则使用反射创建一个  放入  EXTENSION_INSTANCES
                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            //注入其它的扩展  用于扩展点 和 其它的扩展点互通      给当前扩展点  设置其它的扩展点
            injectExtension(instance);
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (CollectionUtils.isNotEmpty(wrapperClasses)) {
                for (Class<?> wrapperClass : wrapperClasses) {
                    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                }
            }

            initExtension(instance);
            return instance;
        } catch (Throwable t) {
            throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
                    type + ") couldn't be instantiated: " + t.getMessage(), t);
        }
    }
private T injectExtension(T instance) {

        if (objectFactory == null) {
            return instance;
        }

        try {
            for (Method method : instance.getClass().getMethods()) {
                // 是否是set方法  参数长度为1   公开的方法
                if (!isSetter(method)) {
                    continue;
                }
                /**
                 * Check {@link DisableInject} to see if we need auto injection for this property
                 */
                if (method.getAnnotation(DisableInject.class) != null) {
                    continue;
                }
                Class<?> pt = method.getParameterTypes()[0];
                if (ReflectUtils.isPrimitives(pt)) {
                    continue;
                }

                try {
                	//如果这个instance里面有其他的属性也是扩展点
                	//那么就通过objectFactory.getExtension(pt, property)方法获得这个属性的实例
                	//并通过set方法(method.invoke(instance, object))设置到instance里面
                    String property = getSetterProperty(method);
                    // 从 objectFactory 得到指定的扩展点
                    Object object = objectFactory.getExtension(pt, property);
                    if (object != null) {
                        // 比如一个set方法是 setRandom(LoadBalance loadBalance)
                        method.invoke(instance, object);
                    }
                } catch (Exception e) {
                    logger.error("Failed to inject via method " + method.getName()
                            + " of interface " + type.getName() + ": " + e.getMessage(), e);
                }

            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return instance;
    }

Adaptive功能实现

Adaptive的主要功能是对所有的扩展点进行封装为一个类,通过URL传入参数的时动态选择需要使用的 扩展点。其底层的实现原理就是动态代理。

public T getAdaptiveExtension() {
        // 双层锁判断
        Object instance = cachedAdaptiveInstance.get();
        if (instance == null) {
            // 如果直接已经有创建并且错误的情况,则直接返回错误信息,防止重复没必要的创建
            if (createAdaptiveInstanceError != null) {
                throw new IllegalStateException("Failed to create adaptive instance: " +
                        createAdaptiveInstanceError.toString(),
                        createAdaptiveInstanceError);
            }

            synchronized (cachedAdaptiveInstance) {
                instance = cachedAdaptiveInstance.get();
                if (instance == null) {
                    try {
                        // 这里真实的进行创建操作
                        instance = createAdaptiveExtension();
                        cachedAdaptiveInstance.set(instance);
                    } catch (Throwable t) {
                        createAdaptiveInstanceError = t;
                        throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
                    }
                }
            }
        }

        return (T) instance;
    }
private T createAdaptiveExtension() {
        try {
            // 这里使用`getAdaptiveExtensionClass`方法进行构建类并且执行实例化
            // 然后和普通的其他class相同,依旧使用injectExtension进行扩展
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
            throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
        }
    }
private Class<?> getAdaptiveExtensionClass() {
        // 确保已经加载了所有的扩展类信息
        getExtensionClasses();
        // 如果已经加载过了,则直接返回
        if (cachedAdaptiveClass != null) {
            return cachedAdaptiveClass;
        }
        // 否则进行构建操作
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }
private Class<?> createAdaptiveExtensionClass() {
        // 实例化一个新的Adaptive的代码生成器,并且进行代码生成
        //通过type和cachedDefaultName获得
        //cachedDefaultName在前面getExtensionClasses()解析@sqi获得
        //通过拼接一个string,拼出来一个类的code作为代理
        String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
        // 获取类加载器
        ClassLoader classLoader = findClassLoader();
        // 通过扩展点,寻找编译器
        org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
        // 编译并且生成class
        return compiler.compile(code, classLoader);
    }

信息缓存接口Directory

Directory是Dubbo中的一个接口,主要用于缓存当前可以被调用的提供者列表信息。我们在消费者进
行调用时都会通过这个接口来获取所有的提供者列表,再进行后续处理。

public interface Directory<T> extends Node {
	// 获取服务的类型
	Class<T> getInterface();
	// 根据本次调用的信息来获取所有可以被执行的提供者信息
	List<Invoker<T>> list(Invocation invocation) throws RpcException; 
	// 获取所有的提供者信息
    List<Invoker<T>> getAllInvokers();
}

进入子类RegistryDirectory#doList 方法

public List<Invoker<T>> doList(Invocation invocation) { 
	// 当没有提供者的时候会直接抛出异常
	if (forbidden) {
	// 1. No service provider 2. Service providers are disabled
		throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "No provider available from registry " + getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please check status of providers(disabled, not registered or in blacklist).");
	}
    List<Invoker<T>> invokers = null;
    try {
		// 交给路由chain去处理并且获取所有的invokers
			invokers = routerChain.route(getConsumerUrl(), invocation); 
		} catch (Throwable t) {
			logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
		}
	return invokers == null ? Collections.emptyList() : invokers;
}

routerChain中的invokers是在refreshInvoker()方法被设置的

private void refreshInvoker(List<URL> invokerUrls) {
        //....
        	//在toinvoke方法中用invoker = new InvokerDelegate<>(protocol.refer(serviceType, url), url, providerUrl)来获取invoker
            Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls);// Translate url list to Invoker map

            /**
             * If the calculation is wrong, it is not processed.
             *
             * 1. The protocol configured by the client is inconsistent with the protocol of the server.
             *    eg: consumer protocol = dubbo, provider only has other protocol services(rest).
             * 2. The registration center is not robust and pushes illegal specification data.
             *
             */
            if (CollectionUtils.isEmptyMap(newUrlInvokerMap)) {
                logger.error(new IllegalStateException("urls to invokers error .invokerUrls.size :" + invokerUrls.size() + ", invoker.size :0. urls :" + invokerUrls
                        .toString()));
                return;
            }

            List<Invoker<T>> newInvokers = Collections.unmodifiableList(new ArrayList<>(newUrlInvokerMap.values()));
            // pre-route and build cache, notice that route cache should build on original Invoker list.
            // toMergeMethodInvokerMap() will wrap some invokers having different groups, those wrapped invokers not should be routed.
            //设置routerChain的Invokers
            routerChain.setInvokers(newInvokers);
            this.invokers = multiGroup ? toMergeInvokerList(newInvokers) : newInvokers;
            this.urlInvokerMap = newUrlInvokerMap;

            try {
                destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap); // Close the unused Invoker
            } catch (Exception e) {
                logger.warn("destroyUnusedInvokers error. ", e);
            }
        }
    }

在protocol的实现类RegistryProtocol可以看到
org.apache.dubbo.registry.integration.RegistryProtocol#refer

// type:需要获得的服务(HelloService) 
// url: 注册中心地址信息
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
		// 获取注册中心的地址URL(主要用于转换协议),比如我们是使用的zookeeper,那么他就会转换为zookeeper://
        url = getRegistryUrl(url);
        // 获取注册中心配置信息
        Registry registry = registryFactory.getRegistry(url);
        if (RegistryService.class.equals(type)) {
            return proxyFactory.getInvoker((T) registry, type, url);
        }

		// 适用于多个分组时使用
        // group="a,b" or group="*"
        Map<String, String> qs = StringUtils.parseQueryString(url.getParameterAndDecoded(REFER_KEY));
        String group = qs.get(GROUP_KEY);
        if (group != null && group.length() > 0) {
            if ((COMMA_SPLIT_PATTERN.split(group)).length > 1 || "*".equals(group)) {
                return doRefer(getMergeableCluster(), registry, type, url);
            }
        }
        // 真正去构建 Invoker  和  Directory
        return doRefer(cluster, registry, type, url);
    }

	//他会把registry注册中心和protocol协议都塞到directory里面,通过cluster封装成invoker
	private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
        // 实例化Directory
        RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
        // 设置注册中心和所使用的协议
        directory.setRegistry(registry);
        directory.setProtocol(protocol);
        // all attributes of REFER_KEY
        //生成监听路径URL
        Map<String, String> parameters = new HashMap<String, String>(directory.getConsumerUrl().getParameters());
        URL subscribeUrl = new URL(CONSUMER_PROTOCOL, parameters.remove(REGISTER_IP_KEY), 0, type.getName(), parameters);
        if (directory.isShouldRegister()) {
            // 在Directory中设置监听的consumerurl地址
            directory.setRegisteredConsumerUrl(subscribeUrl);
            // 在注册中心中注册消费者URL
            // 也就是我们之前的Zookeeper的node中看到的consumer://
            registry.register(directory.getRegisteredConsumerUrl());
        }
        // 构建路由链
        directory.buildRouterChain(subscribeUrl);
        // 进行监听所有的的provider
        directory.subscribe(toSubscribeUrl(subscribeUrl));
        // 加入到集群中
        Invoker<T> invoker = cluster.join(directory);
        List<RegistryProtocolListener> listeners = findRegistryProtocolListeners(url);
        if (CollectionUtils.isEmpty(listeners)) {
            return invoker;
        }

        RegistryInvokerWrapper<T> registryInvokerWrapper = new RegistryInvokerWrapper<>(directory, cluster, invoker, subscribeUrl);

        for (RegistryProtocolListener listener : listeners) {
            listener.onRefer(this, registryInvokerWrapper);
        }
        return registryInvokerWrapper;
    }

回到 RouterChain#route 方法

    public List<Invoker<T>> route(URL url, Invocation invocation) {
        // 所有的Invoker 列表
        List<Invoker<T>> finalInvokers = invokers;
        for (Router router : routers) {
            // 根据路由规则 得到我们最终的Invoker 列表
            finalInvokers = router.route(finalInvokers, url, invocation);
        }
        return finalInvokers;
    }

路由规则实现

org.apache.dubbo.rpc.cluster.router.condition.ConditionRouter

public class ConditionRouter extends AbstractRouter {
    public static final String NAME = "condition";

    private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class);
    protected static final Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
    // 消费者端是否满足判断条件
    // protected static final class MatchPair {
	 	// 满足和不满足的具体条件  或者 匹配 和 不匹配的具体条件
	    //final Set<String> matches = new HashSet<String>();
	    //final Set<String> mismatches = new HashSet<String>();  
	    //}      
    protected Map<String, MatchPair> whenCondition;
    // 当满足判断条件时如何选择invokers(提供者)
    protected Map<String, MatchPair> thenCondition;
    
}

org.apache.dubbo.rpc.cluster.router.condition.ConditionRouter#route

@Override
    public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation)
            throws RpcException {
        // 不启用的时,则直接返回提供者的列表
        if (!enabled) {
            return invokers;
        }

        // 如果不存在任何invoker则直接返回
        if (CollectionUtils.isEmpty(invokers)) {
            return invokers;
        }
        try {
            // 判断是否满足判断条件,不满足直接返回列表
            // 1. 如果判断条件whenCondition为空则直接认定为匹配
        	// 2. 如果whenCondition条件匹配url则认定为匹配
            if (!matchWhen(url, invocation)) {
                return invokers;
            }
            List<Invoker<T>> result = new ArrayList<Invoker<T>>();
            if (thenCondition == null) {
                logger.warn("The current consumer in the service blacklist. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey());
                return result;
            }
            // 依次判断每一个invoker的url是否满足条件
            for (Invoker<T> invoker : invokers) {
                if (matchThen(invoker.getUrl(), url)) {
                    result.add(invoker);
                }
            }
            // 如果不为空则直接返回
            if (!result.isEmpty()) {
                return result;
            } else if (force) {
                // 如果为空,并且必须要走这个条件时,则直接返回空
                logger.warn("The route result is empty and force execute. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey() + ", router: " + url.getParameterAndDecoded(RULE_KEY));
                return result;
            }
        } catch (Throwable t) {
            logger.error("Failed to execute condition router rule: " + getUrl() + ", invokers: " + invokers + ", cause: " + t.getMessage(), t);
        }
        return invokers;
    }

org.apache.dubbo.rpc.cluster.router.condition.ConditionRouter#init

public void init(String rule) {
        try {
            // 必须包含规则配置
            if (rule == null || rule.trim().length() == 0) {
                throw new IllegalArgumentException("Illegal route rule!");
            }
            rule = rule.replace("consumer.", "").replace("provider.", "");
            // 根据"=>"来判断when或者then条件
            int i = rule.indexOf("=>");
            //=>前面是whenRule,后面是thenRule
            //rule=URL.encode("host = 10.20.153.10 => host = 10.20.153.11")
            //=> 之前的为消费者匹配条件,所有参数和消费者的 URL 进行对比,当消费者满足匹配条件时,对该消费者执行后面的过滤规则。
            //=> 之后为提供者地址列表的过滤条件,所有参数和提供者的 URL 进行对比,消费者最终只拿到过滤后的地址列表。
            String whenRule = i < 0 ? null : rule.substring(0, i).trim();
            String thenRule = i < 0 ? rule.trim() : rule.substring(i + 2).trim();
            // 分别根据"=>"来生成前后的规则
            Map<String, MatchPair> when = StringUtils.isBlank(whenRule) || "true".equals(whenRule) ? new HashMap<String, MatchPair>() : parseRule(whenRule);
            Map<String, MatchPair> then = StringUtils.isBlank(thenRule) || "false".equals(thenRule) ? null : parseRule(thenRule);
            this.whenCondition = when;
            this.thenCondition = then;
        } catch (ParseException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

Cluster组件

在org.apache.dubbo.registry.integration.RegistryProtocol#doRefer使用到了

Invoker<T> invoker = cluster.join(directory);

它主要用于代理真正的Invoker执行时做处理,提供了多种容错方案。

//默认使用Failover作为实现
@SPI(FailoverCluster.NAME)
public interface Cluster {

    /**
     * Merge the directory invokers to a virtual invoker.
     *
     * @param <T>
     * @param directory
     * @return cluster invoker
     * @throws RpcException
     */
    // 生成一个新的invoker
    @Adaptive
    <T> Invoker<T> join(Directory<T> directory) throws RpcException;

}

org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster#join

@Override
    public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
        // 使用拦截器进行了一层封装   真正完成生成Invoker的实现 在子类doJoin(directory)
        return buildClusterInterceptors(doJoin(directory), directory.getUrl().getParameter(REFERENCE_INTERCEPTOR_KEY));
    }

进入默认实现类org.apache.dubbo.rpc.cluster.support.FailoverCluster#doJoin

@Override
    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
        // 构建了 FailoverClusterInvoker 对象
        // 最终使用Invoker的时候会使用对应的Invoker的实现类的doinvoke方法
        return new FailoverClusterInvoker<>(directory);
    }

org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke

public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
        // 如果没有任何的invoker则抛出异常
        List<Invoker<T>> copyInvokers = invokers;
        checkInvokers(copyInvokers, invocation);

        // 获取这个方法最大的重试次数
        String methodName = RpcUtils.getMethodName(invocation);
        int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
        if (len <= 0) {
            len = 1;
        }

        // 通过for循环的形式表示可以重试的次数
        RpcException le = null; // last exception.
        List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
        Set<String> providers = new HashSet<String>(len);
        for (int i = 0; i < len; i++) {
            if (i > 0) {
                // 每次都执行一次是否关闭当前consumer的判断
                checkWhetherDestroyed();
                // 重新获取一遍invoker列表
                copyInvokers = list(invocation);
                // 再次进行一次存在invoker的检查
                checkInvokers(copyInvokers, invocation);
            }

            // 选择具体的invoker(交给负载均衡)
            Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);

            // 增加到已经执行过得invoker列表中
            invoked.add(invoker);
            RpcContext.getContext().setInvokers((List) invoked);
            try {
                // 让其真正的去进行执行操作
                Result result = invoker.invoke(invocation);
                if (le != null && logger.isWarnEnabled()) {
                    logger.warn("Although retry the method " + methodName
                            + " in the service " + getInterface().getName()
                            + " was successful by the provider " + invoker.getUrl().getAddress()
                            + ", but there have been failed providers " + providers
                            + " (" + providers.size() + "/" + copyInvokers.size()
                            + ") from the registry " + directory.getUrl().getAddress()
                            + " on the consumer " + NetUtils.getLocalHost()
                            + " using the dubbo version " + Version.getVersion() + ". Last error is: "
                            + le.getMessage(), le);
                }
                return result;
            } catch (RpcException e) {
                // 如果是业务异常则直接抛出
                if (e.isBiz()) {
                    throw e;
                }
                le = e;
            } catch (Throwable e) {
                le = new RpcException(e.getMessage(), e);
            } finally {
                providers.add(invoker.getUrl().getAddress());
            }
        }

        // 如果重试了指定次数后依旧失败,则直接认定为失败
        throw new RpcException(le.getCode(), "Failed to invoke the method "
                + methodName + " in the service " + getInterface().getName()
                + ". Tried " + len + " times of the providers " + providers
                + " (" + providers.size() + "/" + copyInvokers.size()
                + ") from the registry " + directory.getUrl().getAddress()
                + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
                + Version.getVersion() + ". Last error is: "
                + le.getMessage(), le.getCause() != null ? le.getCause() : le);
    }

负载均衡实现

上面使用了负载均衡select(loadbalance, invocation, copyInvokers, invoked);

// 默认使用随机算法
@SPI(RandomLoadBalance.NAME)
public interface LoadBalance {

    /**
     * select one invoker in list.
     *
     * @param invokers   invokers.
     * @param url        refer url
     * @param invocation invocation.
     * @return selected invoker.
     */
    // 进行选择真正的invoker
    @Adaptive("loadbalance")
    <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;

}

进入org.apache.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance#select

public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        // 如果不存在任何的invoker则直接返回
        if (CollectionUtils.isEmpty(invokers)) {
            return null;
        }
        // 如果还有一个invoker则直接返回,不需要执行负载均衡
        if (invokers.size() == 1) {
            return invokers.get(0);
        }
        // 交给子类进行实现
        return doSelect(invokers, url, invocation);
    }

不同的子类有不同的doSelect,这里来看看默认的
org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance#doSelect

protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        // 总计的invoker列表数量
        int length = invokers.size();
        // 默认每个invoker的权重都是相同的
        boolean sameWeight = true;
        // 所有的权重列表
        int[] weights = new int[length];
        // 首个invoker的权重信息
        int firstWeight = getWeight(invokers.get(0), invocation);
        weights[0] = firstWeight;
        // 计算总共的权重,并且吧每一个invoker的权重进行设置到列表中
        int totalWeight = firstWeight;
        for (int i = 1; i < length; i++) {
            int weight = getWeight(invokers.get(i), invocation);
            // save for later use
            weights[i] = weight;
            // Sum
            totalWeight += weight;
            if (sameWeight && weight != firstWeight) {
                sameWeight = false;
            }
        }
        // 如果权重不相同    10   30   50   100
        if (totalWeight > 0 && !sameWeight) {
            // 通过总共的权重来随机分配
            int offset = ThreadLocalRandom.current().nextInt(totalWeight);
            // 看看最终落到哪一个机器上去
            for (int i = 0; i < length; i++) {
                offset -= weights[i];
                if (offset < 0) {
                    return invokers.get(i);
                }
            }
        }
        // 如果权重都是相同的话,则随机选取一个即可
        return invokers.get(ThreadLocalRandom.current().nextInt(length));
    }

Invoker执行逻辑

前面通过LoadBalance获得了Invoker
Invoker就是我们真实执行请求的组件。这里也会衍生出我们真正的 Dubbo 或者 Grpc(谷歌的) 等其他协议的请
求。

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;

}

进入org.apache.dubbo.rpc.protocol.AbstractInvoker#invoke

	public Result invoke(Invocation inv) throws RpcException {
        // 判断系统是否已经关闭
        if (destroyed.get()) {
            logger.warn("Invoker for service " + this + " on consumer " + NetUtils.getLocalHost() + " is destroyed, "
                    + ", dubbo version is " + Version.getVersion() + ", this invoker should not be used any longer");
        }
        RpcInvocation invocation = (RpcInvocation) inv;
        invocation.setInvoker(this);

        // 设置所有的RPCContext中的附加信息
        if (CollectionUtils.isNotEmptyMap(attachment)) {
            invocation.addObjectAttachments(attachment);
        }
        Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
        if (CollectionUtils.isNotEmptyMap(contextAttachments)) {
            invocation.addAttachments(contextAttachments);
        }

        // 获取执行的模式
        invocation.setInvokeMode(RpcUtils.getInvokeMode(url, invocation));
        // 设置执行id,主要用于适配异步模式使用
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);

        // 交给子类进行真正的执行
        AsyncRpcResult asyncResult;
        try {
            asyncResult = (AsyncRpcResult) doInvoke(invocation);
        } catch (InvocationTargetException e) {
            // 业务异常
            Throwable te = e.getTargetException();
            if (te == null) {
                asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
            } else {
                if (te instanceof RpcException) {
                    ((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
                }
                asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, te, invocation);
            }
        } catch (RpcException e) {
            // RPC阶段出现了异常
            if (e.isBiz()) {
                asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
            } else {
                throw e;
            }
        } catch (Throwable e) {
            asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
        }

        // 设置执行的结果信息
        RpcContext.getContext().setFuture(new FutureAdapter(asyncResult.getResponseFuture()));

        // 返回结果
        return asyncResult;
    }

进入子类dubboInvoker
org.apache.dubbo.rpc.protocol.dubbo.DubboInvoker#doInvoke

protected Result doInvoke(final Invocation invocation) throws Throwable {
        RpcInvocation inv = (RpcInvocation) invocation;
        final String methodName = RpcUtils.getMethodName(invocation);
        inv.setAttachment(PATH_KEY, getUrl().getPath());
        inv.setAttachment(VERSION_KEY, version);

        // 传输的客户端
        ExchangeClient currentClient;
        if (clients.length == 1) {
            currentClient = clients[0];
        } else {
            currentClient = clients[index.getAndIncrement() % clients.length];
        }

        try {
            // 是否返回值,也就是相当于发送了一个指令,不在乎服务端的返回
            // 通常适用于异步请求
            boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
            // 获取超时的配置
            int timeout = getUrl().getMethodPositiveParameter(methodName, TIMEOUT_KEY, DEFAULT_TIMEOUT);
            if (isOneway) {
                // 如果不需要返回值信息(异步)
                boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
                // 发送命令
                //最后通过netty或者mina等channel的实现类来send
                currentClient.send(inv, isSent);
                // 告知为异步的结果
                return AsyncRpcResult.newDefaultAsyncResult(invocation);
            } else {
                // 获取真正执行的线程池(ThreadPool中的SPI)
                ExecutorService executor = getCallbackExecutor(getUrl(), inv);
                // 发送请求并且等待结果
                CompletableFuture<AppResponse> appResponseFuture =
                        currentClient.request(inv, timeout, executor).thenApply(obj -> (AppResponse) obj);
                // 在2.6.x中使用,设置完成的额结果信息
                FutureContext.getContext().setCompatibleFuture(appResponseFuture);
                // 创建新的结果信息并且返回
                AsyncRpcResult result = new AsyncRpcResult(appResponseFuture, inv);
                result.setExecutor(executor);
                return result;
            }
        } catch (TimeoutException e) {
            throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
        } catch (RemotingException e) {
            throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值