Dubbo服务端(Service)源码分析(二)

半兽人 发表于: 2018-01-08   最后更新时间: 2018-01-09 09:34:13  
{{totalSubscript}} 订阅, 4,492 游览

screenshot
如上图所示的Dubbo的暴露服务的过程,不难看出它也和消费者端很像,也需要一个像reference的对象来维护service关联的所有对象及其属性,这里的reference就是provider。由于ServiceBean实现了InitializingBean接口,所有在Spring实例化这个bean后会调用接口方法afterPropertiesSet:

public void afterPropertiesSet() throws Exception {  
        //如果没有配置provider  
        if (getProvider() == null) {  
            //获取IOC容器里的所有provider  
            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);  
                        }  
                    }  
                    //关联所有providers  
                    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) {  
                                throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config);  
                            }  
                            providerConfig = config;  
                        }  
                    }  
                    if (providerConfig != null) {  
                        setProvider(providerConfig);  
                    }  
                }  
            }  
        }  
        //如果没有配置application,且没有配置provider  
        if (getApplication() == null  
                && (getProvider() == null || getProvider().getApplication() == null)) {  
            //获取所有applications  
            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;  
                    }  
                }  
                //关联application  
                if (applicationConfig != null) {  
                    setApplication(applicationConfig);  
                }  
            }  
        }  
        //如果没有配置module,且没有配置provider  
        if (getModule() == null  
                && (getProvider() == null || getProvider().getModule() == null)) {  
            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;  
                    }  
                }  
                //关联module  
                if (moduleConfig != null) {  
                    setModule(moduleConfig);  
                }  
            }  
        }  
        //如果没有配置registries,且没有配置provider  
        if ((getRegistries() == null || getRegistries().size() == 0)  
                && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0)  
                && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {  
            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);  
                    }  
                }  
                //关联registries  
                if (registryConfigs != null && registryConfigs.size() > 0) {  
                    super.setRegistries(registryConfigs);  
                }  
            }  
        }  
        //如果没有配置monitor,且没有配置provider  
        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;  
                    }  
                }  
                //关联monitor  
                if (monitorConfig != null) {  
                    setMonitor(monitorConfig);  
                }  
            }  
        }  
        //如果没有配置protocol,且没有配置provider  
        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);  
                    }  
                }  
                //关联protocol  
                if (protocolConfigs != null && protocolConfigs.size() > 0) {  
                    super.setProtocols(protocolConfigs);  
                }  
            }  
        }  
        //如果没有配置path  
        if (getPath() == null || getPath().length() == 0) {  
            if (beanName != null && beanName.length() > 0   
                    && getInterface() != null && getInterface().length() > 0  
                    && beanName.startsWith(getInterface())) {  
                setPath(beanName);  
            }  
        }  
        //暴露provider  
        if (! isDelay()) {  
            export();  
        }  
    }

Dubbo在确认了所有相关对象都配置后调用export方法开始暴露过程:

public synchronized void export() {  
        //如果provider没有配置  
        if (provider != null) {  
            //如果exporter没有配置使用provider所关联的exporter  
            if (export == null) {  
                export = provider.getExport();  
            }  
            //如果delay(延迟暴露)没有配置,获取provider的delay  
            if (delay == null) {  
                delay = provider.getDelay();  
            }  
        }  
        //如果不需要暴露接口则直接返回  
        if (export != null && ! export.booleanValue()) {  
            return;  
        }  
        //如果延迟暴露的时间(毫秒级)是存在的,开启线程并等待delay毫秒后开始暴露接口,否则直接执行暴露接口过程  
        if (delay != null && delay > 0) {  
            Thread thread = new Thread(new Runnable() {  
                public void run() {  
                    try {  
                        Thread.sleep(delay);  
                    } catch (Throwable e) {  
                    }  
                    doExport();  
                }  
            });  
            thread.setDaemon(true);  
            thread.setName("DelayExportServiceThread");  
            thread.start();  
        } else {  
            doExport();  
        }  
    }
protected synchronized void doExport() {  
        //如果不需要暴露接口则抛出异常  
        if (unexported) {  
            throw new IllegalStateException("Already unexported!");  
        }  
        //如果已经暴露则不需要重复暴露  
        if (exported) {  
            return;  
        }  
        exported = true;  
        //如果interfaceName没配置(这样dubbo就无法找到需要暴露的service对象)则抛出异常  
        if (interfaceName == null || interfaceName.length() == 0) {  
            throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");  
        }  
        checkDefault();  
        //provider已经配置的情况下,如果application、module、registries、monitor、protocol中有未配置的均可以从provider获取  
        if (provider != null) {  
            if (application == null) {  
                application = provider.getApplication();  
            }  
            if (module == null) {  
                module = provider.getModule();  
            }  
            if (registries == null) {  
                registries = provider.getRegistries();  
            }  
            if (monitor == null) {  
                monitor = provider.getMonitor();  
            }  
            if (protocols == null) {  
                protocols = provider.getProtocols();  
            }  
        }  
        if (module != null) {  
            if (registries == null) {  
                registries = module.getRegistries();  
            }  
            if (monitor == null) {  
                monitor = module.getMonitor();  
            }  
        }  
        if (application != null) {  
            if (registries == null) {  
                registries = application.getRegistries();  
            }  
            if (monitor == null) {  
                monitor = application.getMonitor();  
            }  
        }  
        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);  
            }  
            checkInterfaceAndMethods(interfaceClass, methods);  
            checkRef();  
            generic = Boolean.FALSE.toString();  
        }  
        //如果是本地服务  
        if(local !=null){  
            //如果是本地服务在interfaceName属性后面加上Local  
            if(local=="true"){  
                local=interfaceName+"Local";  
            }  
            Class<?> localClass;  
            try {  
                //加载service  
                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 {  
                //加载service  
                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  
        checkApplication();  
        //检查registries  
        checkRegistry();  
        //检查protocol  
        checkProtocol();  
        //将所有这些对象的属性关联到provider  
        appendProperties(this);  
        checkStubAndMock(interfaceClass);  
        if (path == null || path.length() == 0) {  
            path = interfaceName;  
        }  
        //暴露地址  
        doExportUrls();  
    }
private void doExportUrls() {  
        //将注册的所有url匹配上对应的协议在服务端暴露出来  
        List<URL> registryURLs = loadRegistries(true);  
        for (ProtocolConfig protocolConfig : protocols) {  
            doExportUrlsFor1Protocol(protocolConfig, registryURLs);  
        }  
    }
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {  
        //如果没配置protocol则默认使用dubbo协议  
        String name = protocolConfig.getName();  
        if (name == null || name.length() == 0) {  
            name = "dubbo";  
        }  
        //获取主机地址  
        String host = protocolConfig.getHost();  
        if (provider != null && (host == null || host.length() == 0)) {  
            host = provider.getHost();  
        }  
        boolean anyhost = false;  
        if (NetUtils.isInvalidLocalHost(host)) {  
            anyhost = true;  
            try {  
                host = InetAddress.getLocalHost().getHostAddress();  
            } catch (UnknownHostException e) {  
                logger.warn(e.getMessage(), e);  
            }  
            if (NetUtils.isInvalidLocalHost(host)) {  
                if (registryURLs != null && registryURLs.size() > 0) {  
                    for (URL registryURL : registryURLs) {  
                        try {  
                            //创建socket,连接到注册中心  
                            Socket socket = new Socket();  
                            try {  
                                SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort());  
                                socket.connect(addr, 1000);  
                                //获取服务所在主机地址  
                                host = socket.getLocalAddress().getHostAddress();  
                                break;  
                            } finally {  
                                try {  
                                    socket.close();  
                                } catch (Throwable e) {}  
                            }  
                        } catch (Exception e) {  
                            logger.warn(e.getMessage(), e);  
                        }  
                    }  
                }  
                if (NetUtils.isInvalidLocalHost(host)) {  
                    host = NetUtils.getLocalHost();  
                }  
            }  
        }  
        //获取协议接口号  
        Integer port = protocolConfig.getPort();  
        if (provider != null && (port == null || port == 0)) {  
            port = provider.getPort();  
        }  
        final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();  
        if (port == null || port == 0) {  
            port = defaultPort;  
        }  
        if (port == null || port <= 0) {  
            port = getRandomPort(name);  
            if (port == null || port < 0) {  
                port = NetUtils.getAvailablePort(defaultPort);  
                putRandomPort(name, port);  
            }  
            logger.warn("Use random available port(" + port + ") for protocol " + name);  
        }  

        //获取application、module、provider、protocol、exporter、registries、monitor所有属性  
        Map<String, String> map = new HashMap<String, String>();  
        if (anyhost) {  
            map.put(Constants.ANYHOST_KEY, "true");  
        }  
        map.put(Constants.SIDE_KEY, Constants.PROVIDER_SIDE);  
        map.put(Constants.DUBBO_VERSION_KEY, Version.getVersion());  
        map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));  
        if (ConfigUtils.getPid() > 0) {  
            map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));  
        }  
        appendParameters(map, application);  
        appendParameters(map, module);  
        appendParameters(map, provider, Constants.DEFAULT_KEY);  
        appendParameters(map, protocolConfig);  
        appendParameters(map, this);  
        if (methods != null && methods.size() > 0) {  
            for (MethodConfig method : methods) {  
                appendParameters(map, method, method.getName());  
                String retryKey = method.getName() + ".retry";  
                if (map.containsKey(retryKey)) {  
                    String retryValue = map.remove(retryKey);  
                    if ("false".equals(retryValue)) {  
                        map.put(method.getName() + ".retries", "0");  
                    }  
                }  
                List<ArgumentConfig> arguments = method.getArguments();  
                if (arguments != null && arguments.size() > 0) {  
                    for (ArgumentConfig argument : arguments) {  
                        //类型自动转换.  
                        if(argument.getType() != null && argument.getType().length() >0){  
                            Method[] methods = interfaceClass.getMethods();  
                            //遍历所有方法  
                            if(methods != null && methods.length > 0){  
                                for (int i = 0; i < methods.length; i++) {  
                                    String methodName = methods[i].getName();  
                                    //匹配方法名称,获取方法签名.  
                                    if(methodName.equals(method.getName())){  
                                        Class<?>[] argtypes = methods[i].getParameterTypes();  
                                        //一个方法中单个callback  
                                        if (argument.getIndex() != -1 ){  
                                            if (argtypes[argument.getIndex()].getName().equals(argument.getType())){  
                                                appendParameters(map, argument, method.getName() + "." + argument.getIndex());  
                                            }else {  
                                                throw new IllegalArgumentException("argument config error : the index attribute and type attirbute not match :index :"+argument.getIndex() + ", type:" + argument.getType());  
                                            }  
                                        } else {  
                                            //一个方法中多个callback  
                                            for (int j = 0 ;j<argtypes.length ;j++) {  
                                                Class<?> argclazz = argtypes[j];  
                                                if (argclazz.getName().equals(argument.getType())){  
                                                    appendParameters(map, argument, method.getName() + "." + j);  
                                                    if (argument.getIndex() != -1 && argument.getIndex() != j){  
                                                        throw new IllegalArgumentException("argument config error : the index attribute and type attirbute not match :index :"+argument.getIndex() + ", type:" + argument.getType());  
                                                    }  
                                                }  
                                            }  
                                        }  
                                    }  
                                }  
                            }  
                        }else if(argument.getIndex() != -1){  
                            appendParameters(map, argument, method.getName() + "." + argument.getIndex());  
                        }else {  
                            throw new IllegalArgumentException("argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");  
                        }  

                    }  
                }  
            } // end of methods for  
        }  

        if (ProtocolUtils.isGeneric(generic)) {  
            map.put("generic", generic);  
            map.put("methods", Constants.ANY_VALUE);  
        } else {  
            String revision = Version.getVersion(interfaceClass, version);  
            if (revision != null && revision.length() > 0) {  
                map.put("revision", revision);  
            }  

            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();  
            if(methods.length == 0) {  
                logger.warn("NO method found in service interface " + interfaceClass.getName());  
                map.put("methods", Constants.ANY_VALUE);  
            }  
            else {  
                map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));  
            }  
        }  
        if (! ConfigUtils.isEmpty(token)) {  
            if (ConfigUtils.isDefault(token)) {  
                map.put("token", UUID.randomUUID().toString());  
            } else {  
                map.put("token", token);  
            }  
        }  
        if ("injvm".equals(protocolConfig.getName())) {  
            protocolConfig.setRegister(false);  
            map.put("notify", "false");  
        }  
        // 导出服务  
        String contextPath = protocolConfig.getContextpath();  
        if ((contextPath == null || contextPath.length() == 0) && provider != null) {  
            contextPath = provider.getContextpath();  
        }  
        //创建服务所在url  
        URL url = new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + path, map);  

        if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)  
                .hasExtension(url.getProtocol())) {  
            url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)  
                    .getExtension(url.getProtocol()).getConfigurator(url).configure(url);  
        }  

        String scope = url.getParameter(Constants.SCOPE_KEY);  
        //配置为none不暴露  
        if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {  

            //配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务)  
            if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {  
                //暴露的地址是localhost所以远端无法访问  
                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);  
                        }  
                        //获取invoker  
                        Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));  
                        //根据协议将invoker暴露成exporter,具体过程是创建一个ExchangeServer,它会绑定一个ServerSocket到配置端口  
                        Exporter<?> exporter = protocol.export(invoker);  
                        //将创建的exporter放进链表便于管理  
                        exporters.add(exporter);  
                    }  
                } else {  
                    Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);  

                    Exporter<?> exporter = protocol.export(invoker);  
                    exporters.add(exporter);  
                }  
            }  
        }  
        this.urls.add(url);  
    }

整个暴露服务的流程就是首先检查配置是否完整然后获取协议和端口信息,通知registries自己已经注册可以提供服务最后创建Server绑定端口。这样用户就可以从配置的信息连接到Server并和Server通信远程调用方法了。

更新于 2018-01-09
在线,10小时前登录

查看dubbo更多相关的文章或提一个关于dubbo的问题,也可以与我们一起分享文章