Dubbo源码学习

ExtensionLoader<T>
  —ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS //final static 存放class与ExtensionLoader对应关系
  —ExtensionFactory objectFactory   //当调用ExtensionLoader#injectExtension方法的时候进行依赖注入
  —cachedAdaptiveClass  //adaptive class如果@adaptive注解在类上,直接返回类,如果注解在方法上动态生成adaptive class

 

 

==========================dubbo SPI=====================================

—>getExtensionLoader(Class<T> type) //获取extentionload
   —>T getAdaptiveExtension() //
     —>createAdaptiveExtension()
       —>injectExtension((T) getAdaptiveExtensionClass().newInstance()) //injecctExtension 依赖注入
         —>getAdaptiveExtensionClass()
           —>getExtensionClasses()
             —>loadExtensionClasses()  //获取type类的所有实现类,以及@SPI注解上的默认实现
               —>loadDirectory(extensionClasses,META-INF/dubbo/internal, type.getName()); //获取路径下type的实现类放入extensionClasses Map中
                 —>loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL)
                   —>loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name)//@adaptive注解在类上cachedAdaptiveClass=clazz
             —>createAdaptiveExtensionClass() //如果注解在方法上动态生成类
               —>createAdaptiveExtensionClassCode()  //生生代码
                 —>compiler.compile(code, classLoader) //生成class类
         —>injectExtension((T)
           —>objectFactory.getExtension(pt, property) //获取set方法需要的class
             —>ExtensionLoader.getExtensionLoader(type).getAdaptiveExtension()

—>getExtensionLoader(Class<T> type) //获取extentionload
  —>getExtension(String name) //获取SPI指定名称的实现类
    —>createExtension(String name)
      —>getExtensionClasses().get(name)//获取制定名称的类
      —>injectExtension(instance)//给类的对象依赖注入
      —>injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance))//ProtocolFilterWrapper ProtocolListenerWrapper装饰者模式一层层嵌入额外处理


总结: 使用adaptive这种机制,可以轻松拓展;
     dubbo 内核对扩展是无感的 , 完全不知道扩展的存在 , 内核代码中不会出现使用具体扩展的硬编码。


========================dubbo 动态编译======================================

—>createAdaptiveExtensionClass()
  —>createAdaptiveExtensionClassCode() //生成动态编译类的代码
  —>compiler.compile(code, classLoader) //编译代码

动态编译生成的代码(取其中的一个方法)为:

public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
   
    public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
        if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
        org.apache.dubbo.common.URL url = arg0.getUrl();
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(org.apache.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
        org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
        return extension.export(arg0);
    }

}

 

=======================dubbo 与spring集成====================================
spring schema自定义拓展
1、编写自定义Schema文件;
2、编写自定义NamespaceHandler;
3、编写解析BeanDefinition的parser
4、在Spring中注册上述组建

dubbo通过自定义Schema是如何配置dubbo里面的核心组件

bubba-provider.xml文件内容:
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- provider's application name, used for tracing dependency relationship -->
    <dubbo:application name="demo-provider"/>

    <!-- use multicast registry center to export service -->
    <dubbo:registry address="zookeeper://10.199.4.108:2181,10.199.4.109:2181,10.199.4.110:2181,10.199.4.111:2181,10.199.4.112:2181"/>

    <!-- use dubbo protocol to export service on port 20880 -->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!-- service implementation, as same as regular local bean -->
    <bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>

    <!-- declare the service interface to be exported -->
    <dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService"/>

</beans>

注:xmlns:dubbo="http://dubbo.apache.org/schema/dubbo中http://dubbo.apache.org/schema/dubbo为处理器类映射路径具体映射关系在spring.handlers中
spring.handlers文件内容为:
http\://dubbo.apache.org/schema/dubbo=org.apache.dubbo.config.spring.schema.DubboNamespaceHandler
http\://code.alibabatech.com/schema/dubbo=org.apache.dubbo.config.spring.schema.DubboNamespaceHandler


DubboNamespaceHandler类中定义各个配置的名称和实体类以及parse类比如:
registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));


http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd 其中http://dubbo.apache.org/schema/dubbo/dubbo.xsd为
dubbo.xsd的文件映射路径,具体的映射关系在在spring.schemas文件中
spring.schemas文件内容为:
http\://dubbo.apache.org/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd
http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/compat/dubbo.xsd

dubbo.xsd文件约束<dubbo>语法

 

=======================dubbo源码 服务暴露============================
                        serviceConfig———>获取ref(对外提供服务的实际类)
                  proxyFactory.geinvoker()——————————————————————————————————————————>invoker
protocol.export()————————————————————————————————————————————————————————————————————————————>exporter

服务暴露分为两个阶段
1、接口实现类转为invoker
spring schema标签里面的service—>serviceBean—>serviceConfig—>proxyFactory—>invoker
2、invoker转为exporter
本地暴露:protocol(inJvmprotocol)—>exporter—>存入exporterMap
—> ServiceConfig.export()
   —>doExport()
     —>appendProperties(this) //从配置文件中获取属性的value,然后为当前对象通过setter 方法来添加属性,完善serviceConfig的属性
     —>doExportUrls
       —>loadRegistries(true) //获取注册中心的地址
       —>doExportUrlsFor1Protocol(protocolConfig, registryURLs) 
         —>appendParameters(map, application) //这个方法的作用就是通过调用当前对象的getter方法获取到传入对象的值然后塞到 map 当中去。用于后面的构造URL这个对象
         —>new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + path, map)
         —>exportLocal(url)
           —>protocol.export(invoker)  //exporter持有invoker的引用,还持有exporterMap的引用. protocol由Protocol$Adaptive.getExtension(name)详解见@2
             —>getInvoker(T proxy, Class<T> type, URL url) //invoker其实就是一个持有proxy,type,url的一个类,然后持有接口的动态代理类wrapper,重写doinvoke方法见@1
                                                             proxy对外提供的实际类ref,type当前接口的Class实例,URL 配置信息的统一格式,所有扩展点都通过传递 URL 携带配置信息
               —>Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type) // //当前接口的代理对象Wrapper实例,动态代理的概念
           exporters.add(exporter) //将exporter放入exporters	Map中





注释***************

@1   return new AbstractProxyInvoker<T>(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName,
                                      Class<?>[] parameterTypes,
                                      Object[] arguments) throws Throwable {
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };

@2  这里的 protocol实例是 本地方法暴露获取的实例。它也是 dubbo 自定义的 SPI 生成的 Protocol$Adaptive通过它的getExtension(name)方法创建 Protocol实例
    Protocol$Adaptive这个类生成的 Protocol对象的结构是:
     .ProtocolListenerWrapper 
       .ProtocolFilterWrapper 
         .InjvmProtocol
    dubbo 的定义 SPI 里面包括 AOP,其实就是获取到所有的 SPI 接口的实例对象



远程暴露:protocol(DubboProtocol)—>HeaderExchanger—>NettyTransporter—>ZookeeperRegister—>exporter—>存入exporterMap

—> ServiceConfig.export()
   —>doExport()
     —>appendProperties(this) //从配置文件中获取属性的value,然后为当前对象通过setter 方法来添加属性,完善serviceConfig的属性
     —>doExportUrls
       —>loadRegistries(true) //获取注册中心的地址
       —>doExportUrlsFor1Protocol(protocolConfig, registryURLs) 
         —>appendParameters(map, application) //这个方法的作用就是通过调用当前对象的getter方法获取到传入对象的值然后塞到 map 当中去。用于后面的构造URL这个对象
         —>new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + path, map)
         —>proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()))
         —>new DelegateProviderMetaDataInvoker(invoker, this)    
         —>protocol.export(wrapperInvoker)   //protocol通过Protocol$Adaptive的getExtension(name)获取 此时name为registry
           —>doLocalExport(originInvoker)
             —>getCacheKey(originInvoker)//通过 Invoker 对象获取到缓存 key,然后再删除 dynamic与enabled 参数 
               —>getProviderUrl(originInvoker)
               —>providerUrl.removeParameters("dynamic", "enabled").toFullString()
             —>(ExporterChangeableWrapper<T>) bounds.get(key) //bounds缓存中根据上面获取的 key 获取 Exporter 对象,如果获取到直接返回;否则进行服务暴露(下面三行) 
                                                               ExporterChangeableWrapper持有Invoker,Exporter的引用
               —>new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker))
               —>new ExporterChangeableWrapper<T>((Exporter<T>) protocol.export(invokerDelegete), originInvoker)//protocol为dubboProtocol
                 —>invoker.getUrl()
                 —>serviceKey(url)
                 —>new DubboExporter<T>(invoker, key, exporterMap)
                 —>exporterMap.put(key, exporter)
                 —>openServer(url) //DubboProtocol#createServer 创建服务,达到服务暴露的目的
                 —>createServer(url) //创建一个 Netty Serve 服务
                   —>Exchangers.bind(url, requestHandler)
                     —>ExtensionLoader.getExtensionLoader(Exchanger.class).getExtension(type).bind(url, requestHandler)
                       —>new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))))
                         —>Transporters.bind(URL url, ChannelHandler... handlers)
                           —>getTransporter().bind(url, handler)
                             —>ExtensionLoader.getExtensionLoader(Transporter.class).getAdaptiveExtension().bind(url, handler) //NettyTransport
                               —>new NettyServer(url, listener)   //打开nettyServer
               —>bounds.put(key, exporter) //
          —>getRegistry(originInvoker) //
            —>getRegistryUrl(originInvoker)
            —>registryFactory.getRegistry(registryUrl) //AbstractRegistryFactory.getRegistry
              —>url.setPath(RegistryService.class.getName())
                .addParameter(Constants.INTERFACE_KEY, RegistryService.class.getName())
                .removeParameters(Constants.EXPORT_KEY, Constants.REFER_KEY) //添加参数interface为com.alibaba.dubbo.registry.RegistryService并去掉export参数
                —>createRegistry(url) //ZookeeperRegistryFactory#createRegistry创建 ZookeeperRegistry 实例 
                  —>zookeeperTransporter.connect()
                —>AbstractRegistry(URL url) //AbstractRegistry构造函数中中调用loadProperties(),在以下目录中保存注册信息 .dubbo\dubbo-registry-127.0.0.1.cache
                —>FailbackRegistry(URL url) //创建线程池 ScheduledExecutorService 检测并连接注册中心,如果失败就就调用 retry()进行重连,高可用
                —>zookeeperTransporter.connect()
        —>exporters.add(exporter)    

 

=======================dubbo源码 服务引用============================

1、把远端服务转化为invoker
2、将invoker转化为客户端需要的接口

 

 

—>ReferenceConfig.createProxy(Map<String, String> map) //
  —>loadRegistries(false)  //加载注册中心配置,因为 dubbo 支持多配置中心,所以返回 URL 的集合
  —>refprotocol.refer(interfaceClass, urls.get(0))  //Protocol$Adaptive  通过注册中心 URL 与 接口 Class 创建 Invoker 调用对象
  —>RegistryProtocol.refer(Class<T> type, URL url)
    —>registryFactory.getRegistry(url) //获取到 zookeeper 注册中心
    —>doRefer(cluster, registry, type, url)
      —>new RegistryDirectory<T>(type, url) //创建注册服务目录 RegistryDirectory 
      —> registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
                    Constants.CHECK_KEY, String.valueOf(false)))  //注册服务消费者 URL 到 zookeeper,其实就是创建 zookeeper 的节点
      —>directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
                Constants.PROVIDERS_CATEGORY
                        + "," + Constants.CONFIGURATORS_CATEGORY
                        + "," + Constants.ROUTERS_CATEGORY))//订阅 zookeeper结点,当服务发生变更时,销毁无效的 Invoke.
        —>DubboProtocol.refer(Class<T> serviceType, URL url)
          —>new DubboInvoker<T>(serviceType, url, getClients(url), invokers) //获取DubboInvoker对象
            —>getClients(url)
              —>new ExchangeClient[connections] //
              —>HeaderExchangeClient(Client client, boolean needHeartbeat)
                —>startHeartbeatTimer()  //开启心跳
          —>invokers.add(invoker) //将创建的 invoker (服务调用者)返回给目录服务,用来刷新 RegistryDirectory 中的Map<String, List<Invoker<T>>> methodInvokerMap对象  
      —>cluster.join(directory) //合并 invoker 创建并提供集群 failover (故障转移)调用策略  MockClusterInvoker
      
  —>proxyFactory.getProxy(invoker)    //通过代理工厂创建远程服务代理返回给使用者
    —>AbstractProxyFactory.getProxy(Invoker<T> invoker, boolean generic) //
      —>JavassistProxyFactory.getProxy(Invoker<T> invoker, Class<?>[] interfaces)
        —>return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker))
          —>InvokerInvocationHandler.invoke(Object proxy, Method method, Object[] args)
            —>new RpcInvocation(method, args)
            —> invoker.invoke(invocation).recreate()
              —>MockClusterInvoker.invoke(Invocation invocation)
                —>FailoverClusterInvoker.doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) //
                  —>DubboInvoker.doInvoke(final Invocation invocation)
                    —>return (Result) currentClient.request(inv, timeout).get()
  

 

======================dubbo源码 Listener & Filter ================================

 

—>ProtocolFilterWrapper. export(Invoker<T> invoker)
  —>protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER))
    —>ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group)  //获取所有的filter
      —> for (int i = filters.size() - 1; i >= 0; i--) //循环filter
         —>filter.invoke(next, invocation)   //将filter包装成一个链  代码见注释@1

注释***************

@1   private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
        Invoker<T> last = invoker;
        List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
        if (filters.size() > 0) {
            for (int i = filters.size() - 1; i >= 0; i--) {
                final Filter filter = filters.get(i);
                final Invoker<T> next = last;
                last = new Invoker<T>() {

                    public Class<T> getInterface() {
                        return invoker.getInterface();
                    }

                    public URL getUrl() {
                        return invoker.getUrl();
                    }

                    public boolean isAvailable() {
                        return invoker.isAvailable();
                    }

                    public Result invoke(Invocation invocation) throws RpcException {
                        return filter.invoke(next, invocation);
                    }

                    public void destroy() {
                        invoker.destroy();
                    }

                    @Override
                    public String toString() {
                        return invoker.toString();
                    }
                };
            }
        }
        return last;
    }




================================dubbo源码分析 集群容错 Invoke===========================

 

—>MockClusterInvoker.invoke(Invocation invocation)
  —>AbstractClusterInvoker.invoke(final Invocation invocation)
    —>list(invocation) //获取 List<Invoker<T>>
      —>directory.list(invocation)
    —>ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
                 .getMethodParameter(RpcUtils.getMethodName(invocation), Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE)) //获取loadbalance
    —>doInvoke(invocation, invokers, loadbalance)


 

===============================dubbo中的设计模式===========================================
工厂模式              dubboSPI
装饰器模式             AOP,IOC
责任链模式             多filter链式组合
观察者模式             zk上的listener

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值