Dubbo源码分析之三:服务的暴露

来源:互联网 发布:百乐淘宝旗舰店 编辑:程序博客网 时间:2024/04/30 22:59

服务的暴露主要集中在 ServiceBean,ServiceConfig 中。类图如下:
ServiceBean类图

先从ApplicationContextAware接口的setApplicationContext 开始
主要是一些监听器兼容性处理

public void setApplicationContext(ApplicationContext applicationContext) {        this.applicationContext = applicationContext;        // 将applicationContext缓存起来        SpringExtensionFactory.addApplicationContext(applicationContext);        // 下面主要是兼容老版本spring的Listener的处理        if (applicationContext != null) {            SPRING_CONTEXT = applicationContext;            try {                Method method = applicationContext.getClass().getMethod("addApplicationListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1                method.invoke(applicationContext, new Object[] {this});                supportedApplicationListener = true;            } catch (Throwable t) {                if (applicationContext instanceof AbstractApplicationContext) {                    try {                        Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1                        if (! method.isAccessible()) {                            method.setAccessible(true);                        }                        method.invoke(applicationContext, new Object[] {this});                        supportedApplicationListener = true;                    } catch (Throwable t2) {                    }                }            }        }    }

ApplicationListener 的实现,启动完成,暴露服务:

public void onApplicationEvent(ApplicationEvent event) {        if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {            if (isDelay() && ! isExported() && ! isUnexported()) {                if (logger.isInfoEnabled()) {                    logger.info("The service ready on spring started. service: " + getInterface());                }                export(); // 在系统启动完成后暴露服务            }        }    }

在afterPropertiesSet 方法中,实现于InitializingBean。
主要是在暴露前的准备工作

public void afterPropertiesSet() throws Exception {        if (getProvider() == null) {            // 在spring中查找ProviderConfig            Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null  : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);            if (providerConfigMap != null && providerConfigMap.size() > 0) {                Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null  : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);                if ((protocolConfigMap == null || protocolConfigMap.size() == 0)                        && providerConfigMap.size() > 1) { // 兼容旧版本                    List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();                    for (ProviderConfig config : providerConfigMap.values()) {                        if (config.isDefault() != null && config.isDefault().booleanValue()) {                            providerConfigs.add(config);                        }                    }                    if (providerConfigs.size() > 0) {                        setProviders(providerConfigs);                    }                } else {                    ProviderConfig providerConfig = null;                    for (ProviderConfig config : providerConfigMap.values()) {                        if (config.isDefault() == null || config.isDefault().booleanValue()) {                            if (providerConfig != null) { // 一个应用只能有一个providerConfig 提供者                                throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config);                            }                            providerConfig = config;                        }                    }                    if (providerConfig != null) {                        setProvider(providerConfig);                    }                }            }        }        if (getApplication() == null                && (getProvider() == null || getProvider().getApplication() == null)) {                //在spring中查找ApplicationConfig            Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);            if (applicationConfigMap != null && applicationConfigMap.size() > 0) {                ApplicationConfig applicationConfig = null;                for (ApplicationConfig config : applicationConfigMap.values()) {                    if (config.isDefault() == null || config.isDefault().booleanValue()) {                        if (applicationConfig != null) { //也不能重复配置                            throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);                        }                        applicationConfig = config;                    }                }                if (applicationConfig != null) {                    setApplication(applicationConfig);                }            }        }        if (getModule() == null                && (getProvider() == null || getProvider().getModule() == null)) {                // 在spring 中查找ModuleConfig            Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);            if (moduleConfigMap != null && moduleConfigMap.size() > 0) {                ModuleConfig moduleConfig = null;                for (ModuleConfig config : moduleConfigMap.values()) {                    if (config.isDefault() == null || config.isDefault().booleanValue()) {                        if (moduleConfig != null) { // 也不能重复                            throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);                        }                        moduleConfig = config;                    }                }                if (moduleConfig != null) {                    setModule(moduleConfig);                }            }        }        if ((getRegistries() == null || getRegistries().size() == 0)                && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0)                && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {                // spring 中查找注册中心的配置            Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);            if (registryConfigMap != null && registryConfigMap.size() > 0) {                List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();                for (RegistryConfig config : registryConfigMap.values()) {                    if (config.isDefault() == null || config.isDefault().booleanValue()) {                        registryConfigs.add(config);                    }                }                if (registryConfigs != null && registryConfigs.size() > 0) {                    super.setRegistries(registryConfigs); // 注册中心可以有多个                }            }        }        if (getMonitor() == null                && (getProvider() == null || getProvider().getMonitor() == null)                && (getApplication() == null || getApplication().getMonitor() == null)) {            Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);            if (monitorConfigMap != null && monitorConfigMap.size() > 0) {                MonitorConfig monitorConfig = null;                for (MonitorConfig config : monitorConfigMap.values()) {                    if (config.isDefault() == null || config.isDefault().booleanValue()) {                        if (monitorConfig != null) { //监视器只能有一个                            throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);                        }                        monitorConfig = config;                    }                }                if (monitorConfig != null) {                    setMonitor(monitorConfig);                }            }        }        if ((getProtocols() == null || getProtocols().size() == 0)                && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0)) {            Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null  : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);            if (protocolConfigMap != null && protocolConfigMap.size() > 0) {                List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();                for (ProtocolConfig config : protocolConfigMap.values()) {                    if (config.isDefault() == null || config.isDefault().booleanValue()) {                        protocolConfigs.add(config);                    }                }                if (protocolConfigs != null && protocolConfigs.size() > 0) {                    super.setProtocols(protocolConfigs); //protocolConfigs 通信协议可以有多个                }            }        }        if (getPath() == null || getPath().length() == 0) {            if (beanName != null && beanName.length() > 0                     && getInterface() != null && getInterface().length() > 0                    && beanName.startsWith(getInterface())) {                setPath(beanName); //服务名称            }        }        if (! isDelay()) {            export(); //没有延迟就会直接导出暴露,就算这里没暴露,onApplicationEvent中也会暴露        }    }

export() 回调用doExport() 方法,doExport 做了很多检查工作:

protected synchronized void doExport() {        。。。// 省略        // 将调用 appendProperties 初始化provider        // 先通过System.getProperty找,如果没找到,再在属性配置文件找        checkDefault();         。。。        if (ref instanceof GenericService) {             // 通用服务,提供动态性支持            interfaceClass = GenericService.class;            if (StringUtils.isEmpty(generic)) {                generic = Boolean.TRUE.toString();//通用服务标识            }        } else {            try {// 自定义服务                interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()                        .getContextClassLoader());            } catch (ClassNotFoundException e) {                throw new IllegalStateException(e.getMessage(), e);            }            // 检查接口与方法的合法性            // 其中有个异常提示语错误:<dubbo:service interface=\"" + interfaceClass.getName() + "\" ... ><dubbo:method name=\"\" ... /></<**dubbo:reference**>             //dubbo:reference应为dubbo:service            checkInterfaceAndMethods(interfaceClass, methods);            checkRef(); //检查引用            generic = Boolean.FALSE.toString(); //通用服务标识        }        if(local !=null){            if(local=="true"){                local=interfaceName+"Local";            }            Class<?> localClass;            try {                localClass = ClassHelper.forNameWithThreadContextClassLoader(local);            } catch (ClassNotFoundException e) {                throw new IllegalStateException(e.getMessage(), e);            }            if(!interfaceClass.isAssignableFrom(localClass)){                throw new IllegalStateException("The local implemention class " + localClass.getName() + " not implement interface " + interfaceName);            }        }        if(stub !=null){            if(stub=="true"){                stub=interfaceName+"Stub";            }            Class<?> stubClass;            try {                stubClass = ClassHelper.forNameWithThreadContextClassLoader(stub);            } catch (ClassNotFoundException e) {                throw new IllegalStateException(e.getMessage(), e);            }            if(!interfaceClass.isAssignableFrom(stubClass)){                throw new IllegalStateException("The stub implemention class " + stubClass.getName() + " not implement interface " + interfaceName);            }        }        // 配置application参数        /*         *          * 先通过System.getProperty找,如果没找到,再在属性配置文件找         * 通过 appendProperties()完成属性的配置         */        checkApplication(); // application 不能为空        checkRegistry(); // 配置注册中心,至少有一个。方式同上        checkProtocol(); // 配置协议,名称默认dubbo,方式同上        appendProperties(this); // 配置服务属性        //检查 local,stub是否存在,是否实现interfaceClass接口,        //是否有指定的构造函数        /*并检查是否mock,有两种方式,          1 return xxx;          2 指定 mock 类         */         checkStubAndMock(interfaceClass);        if (path == null || path.length() == 0) {            path = interfaceName;        }        doExportUrls(); // 导出服务URL至注册中心    }
private void doExportUrls() {        List<URL> registryURLs = loadRegistries(true); // 获得所有注册中心URL        for (ProtocolConfig protocolConfig : protocols) {            // 根据不同的协议分别导出            doExportUrlsFor1Protocol(protocolConfig, registryURLs);        }    }
// 获得所有注册中心URLprotected List<URL> loadRegistries(boolean provider) {        //检查注册中心,包括从配置文件获取(dubbo.registry.address属性,以|分隔)        checkRegistry();         List<URL> registryList = new ArrayList<URL>();        if (registries != null && registries.size() > 0) {            for (RegistryConfig config : registries) {                String address = config.getAddress();                if (address == null || address.length() == 0) {                    address = Constants.ANYHOST_VALUE;                }                // 从系统属性中获取注册中心信息  以;分隔                             String sysaddress = System.getProperty("dubbo.registry.address");                if (sysaddress != null && sysaddress.length() > 0) {                                        address = sysaddress;                }                if (address != null && address.length() > 0                         && ! RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)) {                    Map<String, String> map = new HashMap<String, String>();                    appendParameters(map, application); //将application属性放入map                    appendParameters(map, config); //将config属性放入map                    map.put("path", RegistryService.class.getName());                    map.put("dubbo", Version.getVersion());                    map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));                    if (ConfigUtils.getPid() > 0) {                        map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));                    }                    if (! map.containsKey("protocol")) {                        // 查询注册中心是否支持remote协议                        // 后面会介绍dubbo是怎么发现注册中心的。                        if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension("remote")) {                            map.put("protocol", "remote");                        } else {                            map.put("protocol", "dubbo");                        }                    }                    //将地址与参数拼成url,address可能是以“;”分隔的。                    List<URL> urls = UrlUtils.parseURLs(address, map);                     for (URL url : urls) {                        url = url.addParameter(Constants.REGISTRY_KEY, url.getProtocol());                        url = url.setProtocol(Constants.REGISTRY_PROTOCOL);                        if ((provider && url.getParameter(Constants.REGISTER_KEY, true))                                || (! provider && url.getParameter(Constants.SUBSCRIBE_KEY, true))) {                            registryList.add(url);                        }                    }                }            }        }        return registryList;    }

关于注册中心的发现。针对上面的方法,调用关系为:
getExtensionLoader -〉hasExtension -〉getExtensionClass —>getExtensionClasses -> loadExtensionClasses

 private Map<String, Class<?>> loadExtensionClasses() {        // 获取type 上的SPI注解,确定 type 对应哪些名称。        // 例如:RegisterFactory 对应 dubbo         final SPI defaultAnnotation = type.getAnnotation(SPI.class);        if(defaultAnnotation != null) {            String value = defaultAnnotation.value();            if(value != null && (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];            }        }        Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();        // 重点,从不同的路径或得对应的扩展        loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY); //  META-INF/dubbo/internal/         loadFile(extensionClasses, DUBBO_DIRECTORY);  // META-INF/dubbo/        loadFile(extensionClasses, SERVICES_DIRECTORY); // META-INF/services/        return extensionClasses;    }

我们看一个例子: RegisterFactory
这里写图片描述
内容为:
zookeeper=com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory

现在,我们再看一下doExportUrlsFor1Protocol 方法,是怎么注册服务的。

private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {  。。。 //省略的部分主要是,参数检查,默认值得处理,以及注册需要的数据都存到一个Map中  String scope = url.getParameter(Constants.SCOPE_KEY);        // 配置为none不暴露        if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {            //配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务)            if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {                exportLocal(url);            }            //如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露远程服务)            if (! Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope) ){                if (logger.isInfoEnabled()) {                    logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);                }                if (registryURLs != null && registryURLs.size() > 0                        && url.getParameter("register", true)) {                    for (URL registryURL : registryURLs) {                        url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));                        URL monitorUrl = loadMonitor(registryURL);                        if (monitorUrl != null) {                            url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());                        }                        if (logger.isInfoEnabled()) {                            logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);                        }                        // 通过代理工厂获得一个调用者                        // 关于proxyFactory实例,看下面的截图。默认SPI 名称为:javassist                        Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));            // 执行注册导出,这里使用了registry 协议            // 通过类似上面的方式找到com.alibaba.dubbo.registry.integration.RegistryProtocol            // ProtocolListenerWrapper -> ProtocolFilterWrapper ->RegistryProtocol                        Exporter<?> exporter = protocol.export(invoker);                        exporters.add(exporter);                    }                } else {                    Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);                    Exporter<?> exporter = protocol.export(invoker);                    exporters.add(exporter);                }            }        }}

这里写图片描述

再看看 RegistryProtocol.export 实现

public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {        //export invoker        // 导出本地调用        final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);        //registry provider        // 注册器提供者。        // 假设使用zk,会通过ZookeeperRegistryFactory 获得 ZookeeperRegistry        final Registry registry = getRegistry(originInvoker);        final URL registedProviderUrl = getRegistedProviderUrl(originInvoker); // 注册提供者URL,注册中心会记录此信息        // 最终的注册动作        registry.register(registedProviderUrl);         // 订阅override数据        // FIXME 提供者订阅时,会影响同一JVM即暴露服务,又引用同一服务的的场景,因为subscribed以服务名为缓存的key,导致订阅信息覆盖。        final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registedProviderUrl);        final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl);        overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);        registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);        //保证每次export都返回一个新的exporter实例        return new Exporter<T>() {            public Invoker<T> getInvoker() {                return exporter.getInvoker();            }            public void unexport() {                try {                    exporter.unexport();                } catch (Throwable t) {                    logger.warn(t.getMessage(), t);                }                try {                    registry.unregister(registedProviderUrl);                } catch (Throwable t) {                    logger.warn(t.getMessage(), t);                }                try {                    overrideListeners.remove(overrideSubscribeUrl);                    registry.unsubscribe(overrideSubscribeUrl, overrideSubscribeListener);                } catch (Throwable t) {                    logger.warn(t.getMessage(), t);                }            }        };    }

registry.register -> FailbackRegistry.register -> ZookeeperRegistry.doRegister

protected void doRegister(URL url) {        try {                // 完成节点创建            zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true));        } catch (Throwable e) {            throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);        }    }
0 0