dubbo

【Dubbo】 服务暴露

2017-12-18  本文已影响23人  程序员驿站

问题

  1. dubbo的服务提供者是怎么将服务暴露给注册中心(这里是说zk)
  2. 消费者是怎么从zk获取服务的地址,进行调用的

时序图

未命名文件.png image.png

服务发布种类

本地发布

定义:本地发布是部署在jvm中, 在同一个服务,自己调用自己的接口没必要使用网络来通信

远程发布

暴露服务

(1) 只暴露服务端口:

(2) 向注册中心暴露服务:

暴露服务源码流程

2、ServiceBean实现了下面的接口
InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware

在spring容器启动的时候执行
实现了InitializingBean接口的afterPropertiesSet(),该接口为spring留给开发者的一个hook,系统启动只执行一次

afterPropertiesSet()里面主要干了什么事情呢
构建ProviderConfig 信息(如果集成了spring,这个是在DubboNamespaceHandler初始化的)
构建ApplicationConfig
构建ModuleConfig
构建RegistryConfig
构建MonitorConfig
构建ProtocolConfig

执行ServiceConfig的export()

public synchronized void export() {
        if (provider != null) {
            if (export == null) {
                export = provider.getExport();
            }
            if (delay == null) {
                delay = provider.getDelay();
            }
        }
        // 如果不需要暴露该服务,则就此结束
        if (export != null && ! export.booleanValue()) {
            return;
        }
        // 如果明确指定了想要延迟的时间差,则依赖线程休眠来完成延迟暴露,delay的值只有为-1或null才依赖spring的事件机制完成延迟暴露
        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();
        }
    }

private transient volatile boolean exported;

protected synchronized void doExport() {
        if (unexported) {
            throw new IllegalStateException("Already unexported!");
        }
        //如果发布了就不执行
        if (exported) {
            return;
        }
        // 设置暴露状态
        exported = true;
        if (interfaceName == null || interfaceName.length() == 0) {
            throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
        }
        checkDefault();
        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;
            generic = true;
        } else {
            try {
                interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
                        .getContextClassLoader());
            } catch (ClassNotFoundException e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
            checkInterfaceAndMethods(interfaceClass, methods);
            checkRef();
            generic = false;
        }
        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);
            }
        }
        checkApplication();
        checkRegistry();
        checkProtocol();
        this.parameters = fixApplicationParams(this.parameters);
        appendProperties(this);
        checkStubAndMock(interfaceClass);
        if (path == null || path.length() == 0) {
            path = interfaceName;
        }
        doExportUrls();
    }
private void doExportUrls() {
  // 解析所有的注册中心地址
    List<URL> registryURLs = loadRegistries(true);  
    for (ProtocolConfig protocolConfig : protocols) {
        doExportUrlsFor1Protocol(protocolConfig, registryURLs);
    }
}

调用者如何调用服务

引用服务

(1) 直连引用服务:

(2) 从注册中心发现引用服务:

拦截服务

上一篇 下一篇

猜你喜欢

热点阅读