• 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>映射关系

  • 相关阅读:
    将Emacs Org mode用于GTD任务管理
    以Emacs Org mode为核心的任务管理方案
    Epson L4158打印机安装与配置
    使用wget命令下载网络资源
    Apt下载安装包时Hash校验和不符
    Deep Learning专栏--FFM+Recurrent Entity Network的端到端方案
    Deep Learning专栏--强化学习之从 Policy Gradient 到 A3C(3)
    Deep Learning专栏--强化学习之MDP、Bellman方程(1)
    Deep Learning基础--Softmax求导过程
    Deep Learning基础--随时间反向传播 (BackPropagation Through Time,BPTT)推导
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12490393.html
Copyright © 2020-2023  润新知