dubbo——providers

一、SpringIOC初始化时,dubbo服务启动

前面springIOC——refresh()中提到finishRefresh(),会执行所有的监听器,但不具体,也不知道有什么用。现在发现dubbo服务就是在这启动的。

/*org.springframework.context.support.AbstractApplicationContext#refresh*/
    public void refresh() throws BeansException, IllegalStateException {
        ...
        //这里注册了一个Bean后置处理器
        //beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
        //作用是:实现AppliationListener的Bean初始化时加入一个applicationListeners容器  
        prepareBeanFactory(beanFactory);
        ...
        //执行applicationListeners容器中的applicationListener的方法
        //applicationListener.onApplicationEvent()
        finishRefresh();
        ...
    }  

DubboBootstrapApplicationListener.onApplicationEvent(event):dubbo服务启动与关闭

/* org.apache.dubbo.config.spring.context.OneTimeExecutionApplicationContextEventListener#onApplicationEvent */
    public final void onApplicationEvent(ApplicationEvent event) {
        if (isOriginalEventSource(event) && event instanceof ApplicationContextEvent) {
            onApplicationContextEvent((ApplicationContextEvent) event);
        }
    }

/* org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener#onApplicationContextEvent */
    public void onApplicationContextEvent(ApplicationContextEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            //dubbo服务启动
            onContextRefreshedEvent((ContextRefreshedEvent) event);
        } else if (event instanceof ContextClosedEvent) {
            //dubbo服务关闭
            onContextClosedEvent((ContextClosedEvent) event);
        }
    }

    private void onContextRefreshedEvent(ContextRefreshedEvent event) {
        //构造方法中初始化的this.dubboBootstrap = DubboBootstrap.getInstance();
        dubboBootstrap.start();
    }

    private void onContextClosedEvent(ContextClosedEvent event) {
        dubboBootstrap.stop();
    }

二、dubbo服务启动——DubboBootstrap.start();

    public DubboBootstrap start() {
        if (started.compareAndSet(false, true)) {
            //初始化
            initialize();
            if (logger.isInfoEnabled()) {
                logger.info(NAME + " is starting...");
            }
            // 暴露dubbo服务(<dubbo:service />注册到注册表)
            exportServices();

            // Not only provider register
            if (!isOnlyRegisterProvider() || hasExportedServices()) {
                // 2. export MetadataService
                exportMetadataService();
                //3. Register the local ServiceInstance if required
                registerServiceInstance();
            }

            //引用dubbo服务(<dubbo:reference /> 创建代理)
            referServices();

            if (logger.isInfoEnabled()) {
                logger.info(NAME + " has started.");
            }
        }
        return this;
    }

1、initialize():初始化

    private void initialize() {
        if (!initialized.compareAndSet(false, true)) {
            //已初始化直接返回,CAS保证原子性
            return;
        }
        //扩展点加载机制,SPI的强化版,强在哪里现在还不知道
        //实例化META-INF/dubbo/internal/org.apache.dubbo.common.context.FrameworkExt文件中的三个类
        //org.apache.dubbo.common.config.Environment : 环境变量组件,在new DubboBootstrap()时,已经实例化,这里拿的是缓存,下面的configManager也是。
        //org.apache.dubbo.rpc.model.ServiceRepository : Service仓库初始化了两个类EchoService、GenericService
        //org.apache.dubbo.config.context.ConfigManager : dubbo所有的配置信息。
        // 所有配置的父类AbstractConfig.addIntoConfigManager()被@PostConstruct注解,Bean初始化后会写入configManager
        ApplicationModel.initFrameworkExts();

        //外部配置读取,对应<dubbo:config-center />,一般未设置
        startConfigCenter();

        //configManager.configCenter为空时,
        //使用<dubbo:registry />中配置创建ConfigCenter
//<dubbo:registry address="" />默认的zookeeper,根据address连接zookeeper并获取配置信息,(这里只是获取配置信息,并不是注册)
useRegistryAsConfigCenterIfNecessary(); //加载生成registryId ProtocolId loadRemoteConfigs(); //验证标签所有属性 //application、Metadata、Provider、Consumer、Monitor、Metrics、Module、Ssl checkGlobalConfigs(); //初始化元数据服务 initMetadataService(); //初始化事件监听器 initEventListener(); if (logger.isInfoEnabled()) { logger.info(NAME + " has been initialized!"); } }

2、exportServices():注册服务

/* org.apache.dubbo.config.bootstrap.DubboBootstrap#exportServices */
    private void exportServices() {
        //遍历所有<dubbo:service />生成的ServiceBean
        configManager.getServices().forEach(sc -> {
            // 与ServiceConfig完全兼容
            ServiceConfig serviceConfig = (ServiceConfig) sc;
            serviceConfig.setBootstrap(this);

            if (exportAsync) {
                //异步注册
                ExecutorService executor = executorRepository.getServiceExporterExecutor();
                Future<?> future = executor.submit(() -> {
                    sc.export();
                });
                asyncExportingFutures.add(future);
            } else {
                //同步注册
                sc.export();
                exportedServices.add(sc);
            }
        });
    }
sc.export():service注册
    public synchronized void export() {
        if (!shouldExport()) {
            //不需要注册,<dubbo:service export="false"/>新标签 官网好像没有更新
            return;
        }

        if (bootstrap == null) {
            //BootStrap未启动,自动启动
            bootstrap = DubboBootstrap.getInstance();
            bootstrap.init();
        }

        //检查并更新子设置 ①
        checkAndUpdateSubConfigs();

        //初始化serviceMatadata属性
        //版本 组名 接口类型 接口名称 实现接口的Bean实例
        serviceMetadata.setVersion(version);
        serviceMetadata.setGroup(group);
        serviceMetadata.setDefaultGroup(group);
        serviceMetadata.setServiceType(getInterfaceClass());
        serviceMetadata.setServiceInterfaceName(getInterface());
        serviceMetadata.setTarget(getRef());

        if (shouldDelay()) {
            //延迟注册
            //<dubbo:service delay="1000"/>
            DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS);
        } else {
            //直接注册 ②
            doExport(); 
        }
        //注册后 ③
        exported();
    }
① checkAndUpdateSubConfigs():校验设置并更新一些默认设置
    private void checkAndUpdateSubConfigs() {
        // 使用全局范围显式定义的默认配置
        // <dubbo:provider/> <dubbo:protocol/>
        completeCompoundConfigs();
        checkDefault();
        checkProtocol();
        // 初始化一些空设置
        List<ConfigInitializer> configInitializers = ExtensionLoader.getExtensionLoader(ConfigInitializer.class)
                .getActivateExtension(URL.valueOf("configInitializer://"), (String[]) null);
        configInitializers.forEach(e -> e.initServiceConfig(this));

        // if protocol is not injvm checkRegistry
        if (!isOnlyInJvm()) {
            //如果protocol不是内部调用(injvm)
            //检查registry设置
            checkRegistry();
        }
        //environment中的值覆盖service属性
        this.refresh();

        if (StringUtils.isEmpty(interfaceName)) {
            //interface属性必需
            throw new IllegalStateException("<dubbo:service interface="" /> interface not allow null!");
        }

        if (ref instanceof GenericService) {
            //如果实际Bean实现了GenericService接口,常用服务bean
            //interfaceClass = GenericService.class
            interfaceClass = GenericService.class;
            if (StringUtils.isEmpty(generic)) {
                generic = Boolean.TRUE.toString();
            }
        } else {
            try {
                //不是GenericService接口类型,根据interfaceClass = Class.forName(interfaceName)
                interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
                        .getContextClassLoader());
            } catch (ClassNotFoundException e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
            //检查接口方法都实现了
            checkInterfaceAndMethods(interfaceClass, getMethods());
            //bean实例不为空
            checkRef();
            generic = Boolean.FALSE.toString();
        }
        if (local != null) {
            //配置<dubbo:service local="true"/>时
            if ("true".equals(local)) {
                local = interfaceName + "Local";
            }
            Class<?> localClass;
            try {
                //初始化代理类localClass = ClassforName(interfaceName+"Local")
                localClass = ClassUtils.forNameWithThreadContextClassLoader(local);
            } catch (ClassNotFoundException e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
            if (!interfaceClass.isAssignableFrom(localClass)) {
                throw new IllegalStateException("The local implementation class " + localClass.getName() + " not implement interface " + interfaceName);
            }
        }
        if (stub != null) {
            //配置<dubbo:service local="true"/>时
            if ("true".equals(stub)) {
                stub = interfaceName + "Stub";
            }
            Class<?> stubClass;
            try {
                //初始化代理类stubClass = ClassforName(interfaceName+"Local")
                stubClass = ClassUtils.forNameWithThreadContextClassLoader(stub);
            } catch (ClassNotFoundException e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
            if (!interfaceClass.isAssignableFrom(stubClass)) {
                throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + interfaceName);
            }
        }
        //检查若配置了local或stub,localClass或stubClass必须是interfaceClass的子类
        checkStubAndLocal(interfaceClass);
        ConfigValidationUtils.checkMock(interfaceClass, this);
        //检查serviceconfig的属性
        ConfigValidationUtils.validateServiceConfig(this);
        //配置后置处理器ConfigPostProcess,类似于BeanPostProcessor
        postProcessConfig();
    }

② doExport():准备url,然后注册

/* org.apache.dubbo.config.ServiceConfig#doExport */
    protected synchronized void doExport() {
        if (unexported) {
            throw new IllegalStateException("The service " + interfaceClass.getName() + " has already unexported!");
        }
        //已注册的直接返回
        if (exported) {
            return;
        }
        exported = true;

        if (StringUtils.isEmpty(path)) {
            //设置path默认值为接口名
            path = interfaceName;
        }
        doExportUrls();
    }

    private void doExportUrls() {
        //前面创建服务仓库ServiceRepository
        ServiceRepository repository = ApplicationModel.getServiceRepository();
        //将Service注册到服务仓库ServiceRepository的services中
        ServiceDescriptor serviceDescriptor = repository.registerService(getInterfaceClass());
        //将Service注册到服务仓库ServiceRepository的providers中
        repository.registerProvider(
                getUniqueServiceName(),
                ref,
                serviceDescriptor,
                this,
                serviceMetadata
        );

        //生成registryURLs格式如下
        // registry://mcip:2291/org.apache.dubbo.registry.RegistryService?application=dubbo-demo&backup=mcip:2292,mcip:2293&dubbo=2.0.2&pid=13252&registry=zookeeper&release=2.7.5&timestamp=1584191484814
        List<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true);

        //<dubbo:protocol name="dubbo" port="${dubbo.port}" />
        for (ProtocolConfig protocolConfig : protocols) {
            //服务路径=protocol的contexpath属性+service的path+group+version
            String pathKey = URL.buildKey(getContextPath(protocolConfig)
                    .map(p -> p + "/" + path)
                    .orElse(path), group, version);
            // 如果指定了特殊路径,再次注入到服务仓库ServiceRepository的services中,
            // 未指定同名覆盖
            repository.registerService(pathKey, interfaceClass);
            // TODO, uncomment this line once service key is unified
            //设置到serviceMetadata中
            serviceMetadata.setServiceKey(pathKey);
            doExportUrlsFor1Protocol(protocolConfig, registryURLs);
        }
    }

    private void doExportUrls() {
        //前面创建服务仓库ServiceRepository
        ServiceRepository repository = ApplicationModel.getServiceRepository();
        //将Service注册到服务仓库ServiceRepository的services中
        ServiceDescriptor serviceDescriptor = repository.registerService(getInterfaceClass());
        //将Service注册到服务仓库ServiceRepository的providers中
        repository.registerProvider(
                getUniqueServiceName(),
                ref,
                serviceDescriptor,
                this,
                serviceMetadata
        );

        //生成registryURLs格式如下
        // registry://mcip:2291/org.apache.dubbo.registry.RegistryService?application=dubbo-demo&backup=mcip:2292,mcip:2293&dubbo=2.0.2&pid=13252&registry=zookeeper&release=2.7.5&timestamp=1584191484814
        List<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true);

        //<dubbo:protocol name="dubbo" port="${dubbo.port}" />
        for (ProtocolConfig protocolConfig : protocols) {
            //服务路径=protocol的contexpath属性+service的path+group+version
            String pathKey = URL.buildKey(getContextPath(protocolConfig)
                    .map(p -> p + "/" + path)
                    .orElse(path), group, version);
            // 如果指定了特殊路径,再次注入到服务仓库ServiceRepository的services中,
            // 未指定同名覆盖
            repository.registerService(pathKey, interfaceClass);
            // TODO, uncomment this line once service key is unified
            //设置到serviceMetadata中
            serviceMetadata.setServiceKey(pathKey);
            //注册
            doExportUrlsFor1Protocol(protocolConfig, registryURLs);
        }
    }

   private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
        String name = protocolConfig.getName();
        if (StringUtils.isEmpty(name)) {
            //<dubbo:protocol name=""/>默认为dubbo
            name = DUBBO;
        }

        Map<String, String> map = new HashMap<String, String>();
        //map.put("side","provider")
        map.put(SIDE_KEY, PROVIDER_SIDE);
        //map.put("release","2.7.5") dubbo版本号
        //map.put("dubbo","2.0.2")大版本号
        //map.put("pid",13252)进程号
        //map.put("timestamp","1584192663652")时间戳
        ServiceConfig.appendRuntimeParameters(map);
        AbstractConfig.appendParameters(map, getMetrics());
        //map.put("application","dubbo-demo") 应用名
        AbstractConfig.appendParameters(map, getApplication());
        //map.put("module","") 模块名
        AbstractConfig.appendParameters(map, getModule());
        //map.put("dynamic","true") service的dynamic默认true,动态注册
        //map.put("deprecated","false") service的deprecated默认false,作废标志
        AbstractConfig.appendParameters(map, provider);
        AbstractConfig.appendParameters(map, protocolConfig);
        //map.put("interface","org.study.service.UserService") service的path 默认接口名
        //map.put("generic","false") service的接口是否实现了GenericService
        AbstractConfig.appendParameters(map, this);
        MetadataReportConfig metadataReportConfig = getMetadataReportConfig();
        if (metadataReportConfig != null && metadataReportConfig.isValid()) {
            map.putIfAbsent(METADATA_KEY, REMOTE_METADATA_STORAGE_TYPE);
        }
        //方法设置
        if (CollectionUtils.isNotEmpty(getMethods())) {
            //...一般为空跳过
        }

        if (ProtocolUtils.isGeneric(generic)) {
            //genericService设置
            map.put(GENERIC_KEY, generic);
            map.put(METHODS_KEY, ANY_VALUE);
        } else {
            //接口版本号,跟随jar包 例如:1.0-SNAPSHOT
            String revision = Version.getVersion(interfaceClass, version);
            if (revision != null && revision.length() > 0) {
                map.put(REVISION_KEY, revision);
            }
            //接口的方法名数组
            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
            if (methods.length == 0) {
                logger.warn("No method found in service interface " + interfaceClass.getName());
                //空方法标志map.put("methods","*")
                map.put(METHODS_KEY, ANY_VALUE);
            } else {
                //方法数组字符串map.put("methods","insert,update")
                map.put(METHODS_KEY, StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
            }
        }

        /**
         * Service的token验证
         */
        if(ConfigUtils.isEmpty(token) && provider != null) {
            token = provider.getToken();
        }

        if (!ConfigUtils.isEmpty(token)) {
            if (ConfigUtils.isDefault(token)) {
                map.put(TOKEN_KEY, UUID.randomUUID().toString());
            } else {
                map.put(TOKEN_KEY, token);
            }
        }
        //map放入到serviceMetadata中
        serviceMetadata.getAttachments().putAll(map);

        // 获取协议host,默认获取本机ip <dubbo:protocol host="" />
        String host = findConfigedHosts(protocolConfig, registryURLs, map);
        //获取协议port,dubbo默认20880 <dubbo:protocol port="" />
        Integer port = findConfigedPorts(protocolConfig, name, map);
        //生成url格式如下
        //dubbo://192.168.56.1:20880/org.study.service.UserService?anyhost=true&application=dubbo-demo&bind.ip=192.168.56.1&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.study.service.UserService&methods=getUserById,update,insert,transactionalTest,getUserByUserId,delete&pid=13252&release=2.7.5&revision=1.0-SNAPSHOT&side=provider&timestamp=1584192937036
        URL url = new URL(name, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), map);

        // You can customize Configurator to append extra parameters
        if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
                .hasExtension(url.getProtocol())) {
            url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
                    .getExtension(url.getProtocol()).getConfigurator(url).configure(url);
        }

        //获取作用域scope属性
        String scope = url.getParameter(SCOPE_KEY);
        // scope == "none",不注册,一般为null
        if (!SCOPE_NONE.equalsIgnoreCase(scope)) {

            // export to local if the config is not remote (export to remote only when config is remote)
            if (!SCOPE_REMOTE.equalsIgnoreCase(scope)) {
                //scope != "remote" ,注册到本地,一般为null会注册到本地
                exportLocal(url);
            }
            // export to remote if the config is not local (export to local only when config is local)
            if (!SCOPE_LOCAL.equalsIgnoreCase(scope)) {
                //scope != "local" ,注册到注册表,一般为null会注册到注册表
                if (CollectionUtils.isNotEmpty(registryURLs)) {
                    for (URL registryURL : registryURLs) {
                        //if protocol is only injvm ,not register
                        if (LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
                            //injvm,内部调用不注册
                            continue;
                        }
                        //url存在dynamic保留,不存在赋值为registryURL的dynamic属性值
                        url = url.addParameterIfAbsent(DYNAMIC_KEY, registryURL.getParameter(DYNAMIC_KEY));
                        //监控的url
                        URL monitorUrl = ConfigValidationUtils.loadMonitor(this, registryURL);
                        if (monitorUrl != null) {
                            url = url.addParameterAndEncoded(MONITOR_KEY, monitorUrl.toFullString());
                        }
                        if (logger.isInfoEnabled()) {
                            if (url.getParameter(REGISTER_KEY, true)) {
                                logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
                            } else {
                                logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
                            }
                        }

                        // provider代理属性 一般为null
                        String proxy = url.getParameter(PROXY_KEY);
                        if (StringUtils.isNotEmpty(proxy)) {
                            registryURL = registryURL.addParameter(PROXY_KEY, proxy);
                        }
                        //创建一个AbstractProxyInvoker的子类实例new AbstractProxyInvoker(ref, interfaceClass,rul)
                        Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
                        //包装器
                        DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
                        //默认DubboProtocol.export注册到远程注册表zookeeper中
                        Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
                        exporters.add(exporter);
                    }
                } else {
                    if (logger.isInfoEnabled()) {
                        logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
                    }
                    Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, url);
                    DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);

                    Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
                    exporters.add(exporter);
                }
                /**
                 * @since 2.7.0
                 * ServiceData Store
                 */
                WritableMetadataService metadataService = WritableMetadataService.getExtension(url.getParameter(METADATA_KEY, DEFAULT_METADATA_STORAGE_TYPE));
                if (metadataService != null) {
                    metadataService.publishServiceDefinition(url);
                }
            }
        }
        this.urls.add(url);
    }
Exporter<?> exporter = PROTOCOL.export(wrapperInvoker):注册服务到zookeeper
PROTOCOL是javassist生成的protocol的代理对象,下面是代理对象的类,代理的是RegistryProtocol而不是DubboProtocol
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
    public void destroy() {
        throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
    }

    public int getDefaultPort() {
        throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
    }

    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");
        //debug : invoker.getUrl()=registry://mcip:2291/org.apache.dubbo.registry.RegistryService?application=dubbo-demo&backup=mcip:2292,mcip:2293&dubbo=2.0.2&export=dubbo%3A%2F%2F192.168.56.1%3A20880%2Forg.study.service.UserService%3Fanyhost%3Dtrue%26application%3Ddubbo-demo%26bind.ip%3D192.168.56.1%26bind.port%3D20880%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.study.service.UserService%26methods%3DgetUserById%2Cupdate%2Cinsert%2CtransactionalTest%2CgetUserByUserId%2Cdelete%26pid%3D12956%26release%3D2.7.5%26revision%3D1.0-SNAPSHOT%26side%3Dprovider%26timestamp%3D1584262152345&pid=12956&registry=zookeeper&release=2.7.5&timestamp=1584262152342
        org.apache.dubbo.common.URL url = arg0.getUrl();
        //debug:url.getProtocol() = "registry"
        //根据META_INF/dubbo/internal/org.apache.dubbo.rpc.protocol文件
        //registry=org.apache.dubbo.registry.integration.RegistryProtocol
        //一直以为是DubboProtocol,但是DubboProtocol中没有注册到zookeeper的逻辑
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Failed 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);
    }

    public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException {
        if (arg1 == null) throw new IllegalArgumentException("url == null");
        org.apache.dubbo.common.URL url = arg1;
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Failed 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.refer(arg0, arg1);
    }

    public java.util.List getServers() {
        throw new UnsupportedOperationException("The method public default java.util.List org.apache.dubbo.rpc.Protocol.getServers() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
    }
}

 RegistryProtocol.export():远程注册,并Map<url,Service>容器

/* org.apache.dubbo.registry.integration.RegistryProtocol#export */
    public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
        //注册url,zookeeper
        //zookeeper://mcip:2291/org.apache.dubbo.registry.RegistryService?application=dubbo-demo&backup=mcip:2292,mcip:2293&dubbo=2.0.2&export=dubbo%3A%2F%2F192.168.56.1%3A20880%2Forg.study.service.UserService%3Fanyhost%3Dtrue%26application%3Ddubbo-demo%26bind.ip%3D192.168.56.1%26bind.port%3D20880%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.study.service.UserService%26methods%3DgetUserById%2Cupdate%2Cinsert%2CtransactionalTest%2CgetUserByUserId%2Cdelete%26pid%3D12956%26release%3D2.7.5%26revision%3D1.0-SNAPSHOT%26side%3Dprovider%26timestamp%3D1584262152345&pid=12956&release=2.7.5&timestamp=1584262152342
        URL registryUrl = getRegistryUrl(originInvoker);
        // 暴露服务的url
        //dubbo://192.168.56.1:20880/org.study.service.UserService?anyhost=true&application=dubbo-demo&bind.ip=192.168.56.1&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.study.service.UserService&methods=getUserById,update,insert,transactionalTest,getUserByUserId,delete&pid=12956&release=2.7.5&revision=1.0-SNAPSHOT&side=provider&timestamp=1584262152345
        URL providerUrl = getProviderUrl(originInvoker);

        // Subscribe the override data
        // FIXME When the provider subscribes, it will affect the scene : a certain JVM exposes the service and call
        //  the same service. Because the subscribed is cached key with the name of the service, it causes the
        //  subscription information to cover.
        //生成最终url
        //provider://192.168.56.1:20880/org.study.service.UserService?anyhost=true&application=dubbo-demo&bind.ip=192.168.56.1&bind.port=20880&category=configurators&check=false&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.study.service.UserService&methods=getUserById,update,insert,transactionalTest,getUserByUserId,delete&pid=12956&release=2.7.5&revision=1.0-SNAPSHOT&side=provider&timestamp=1584262152345
        final URL overrideSubscribeUrl = getSubscribedOverrideUrl(providerUrl);
        //url与service绑定,放入容器中,远程调用时根据url找到serviceimpl
        final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker);
        overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);

        providerUrl = overrideUrlWithConfig(providerUrl, overrideSubscribeListener);
        //注册invoker到本地dubbo.expo
//调用DubboProtocol.export,其中openServer开启netty监听,这个地方不清楚,以后研究netty后再回来看
final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker, providerUrl); // 最终的注册到zookeeper final Registry registry = getRegistry(originInvoker); final URL registeredProviderUrl = getUrlToRegistry(providerUrl, registryUrl); // decide if we need to delay publish boolean register = providerUrl.getParameter(REGISTER_KEY, true); if (register) { //服务注册 // 以zookeeper为例,建立一个znode // /dubbo/org.study.service.UserDubboService2/providers/dubbo%3A%2F%2F192.168.56.1%3A20880%2Forg.study.service.UserDubboService2%3Fanyhost%3Dtrue%26application%3Ddubbo-demo%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.study.service.UserDubboService2%26methods%3DgetUserByUserId%26pid%3D1376%26release%3D2.7.5%26revision%3D1.0-SNAPSHOT%26side%3Dprovider%26timestamp%3D1584271781245 register(registryUrl, registeredProviderUrl); } // 这里是注册目录节点 // /dubbo/org.study.service.UserDubboService2/configurators registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener); //记录registerUrl与subscribeUrl exporter.setRegisterUrl(registeredProviderUrl); exporter.setSubscribeUrl(overrideSubscribeUrl); //确认注册完 notifyExport(exporter); //Ensure that a new exporter instance is returned every time export return new DestroyableExporter<>(exporter); }

总结:

service主要作用就是在注册表注册,例如最终在zookeeper目录结构建立节点;然后本地保存<url,service>映射关系

原文地址:https://www.cnblogs.com/wqff-biubiu/p/12490393.html