código fuente de dubbo - exportación de servicios

En conclusión

La llamada exportación de servicios significa que el proveedor de servicios registra el servicio local en el clúster zk y abre netty para recibir solicitudes de los consumidores. También podemos pensar que el proveedor de servicios dubbo es un servidor netty.

Para la exportación del servicio se realizarán los siguientes pasos:
1. Realizar alguna verificación, valor de parámetro, asignación, etc. (anulación de la misma configuración de parámetros)
2. Obtener todos los registros y obtener todos los protocolos configurados
3. Ensamblar objetos url, desde dubbo se basa en la URL para completar el registro, primero empalmará y ensamblará la URL
4. Generará el objeto Invoker de acuerdo con la URL y el registro (Centro de registro)
5. Envuelva el objeto Invoker y luego realice la exportación real
5.1 Primero, se basará en la ip y el puerto del servicio, abrirá un servicio netty
5.2 y luego convertirá la URL en un nodo zk, y se registrará, de hecho, se registrará en el registro, por ejemplo:
información de la ruta de monitoreo de zookeeper 5.3 aquí necesita ser reconfirmado y aprendido)

Por lo tanto, podemos pensar que la exportación del servicio se divide en dos pasos principales:
1. Verificación de parámetros, parámetros de ensamblaje
2. Exposición del servicio al control remoto
Cuando se expone al control remoto, se dividirá en los siguientes pasos
2.1 Abrir un servicio neto
2.2 Registrarse en zk

Exportar código fuente

La versión que estoy estudiando todavía es la 2.6, por lo que habrá algunas diferencias con el código de la 2.7. El código fuente
exportado por el servicio dubbo puede entenderse como

com.alibaba.dubbo.config.spring.ServiceBean#onApplicationEvent

Comenzando con esta línea de código, después de que se inicia el contenedor de resorte, se producirá un evento ContextRefreshedEvent. Después de que dubbo escuche el evento, comenzará a exportar el servicio
. Para obtener detalles sobre cómo dubbo usa los puntos de extensión de resorte para completar la inicialización, consulte a este blog -> ¿Cómo dubbo usa los puntos de extensión de primavera para completar la inicialización?

com.alibaba.dubbo.config.ServiceConfig#export
public synchronized void export() {
    
    
        if (provider != null) {
    
    
            if (export == null) {
    
    
                export = provider.getExport();
            }
            if (delay == null) {
    
    
                delay = provider.getDelay();
            }
        }
        /**
         * 1.判断是否已经导出,如果已经导出,return
         * 2.判断是否是延迟导出
         * 3.如果是非延迟导出,就进行服务导出
         */
        if (export != null && !export) {
    
    
            return;
        }

        if (delay != null && delay > 0) {
    
    
            delayExportExecutor.schedule(new Runnable() {
    
    
                @Override
                public void run() {
    
    
                    doExport();
                }
            }, delay, TimeUnit.MILLISECONDS);
        } else {
    
    
            doExport();
        }
    }

En el método doExport (), habrá una serie de asignaciones de parámetros y verificaciones. Aquí daré una captura de pantalla

Inserte la descripción de la imagen aquí
El doExportUrls aquí es para exportar el servicio

private void doExportUrls() {
    
    
    /**
         * 如果是多注册中心,这里会获取到所有配置的注册中心
         */
    List<URL> registryURLs = loadRegistries(true);
    /**
         * 如果是多个协议,这里会循环多个协议
         */
    for (ProtocolConfig protocolConfig : protocols) {
    
    
        doExportUrlsFor1Protocol(protocolConfig, registryURLs);
    }
}

doExportUrlsFor1Protocol () En este método, en resumen, se completan dos cosas:
1. Ensamblar y volver a empalmar la URL
2. Realizar exportación de servicio real
En este método, se juzgará de acuerdo con el atributo de alcance configurado por el proveedor de servicios. al servicio local o remoto
Al exportar el servicio, se generará un objeto Invoker según el proveedor del servicio, y luego se exportará el objeto Invoker.

Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
Exporter<?> exporter = protocol.export(wrapperInvoker);

Cuando se llama al método protocol.export (), los siguientes enlaces de llamada se pasarán a su vez

org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper#export
org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper#export
org.apache.dubbo.qos.protocol.QosProtocolWrapper#export
org.apache.dubbo.registry.integration.RegistryProtocol#export

La secuencia de llamada aquí está relacionada con el mecanismo spi de dubbo. Lo que hace cada exportación se analiza más adelante. El
trabajo principal está en el método de exportación org.apache.dubbo.registry.integration.RegistryProtocol #.

@Override
public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
    
    
    //export invoker
    /**
    * 1、导出服务,创建nettyServer
    * 这里是调用的是DubboProtocol的export方法来开启netty服务的
    */
    final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);

    //获取注册中心的URL, zookeeper://ip:port/xxxxx
    URL registryUrl = getRegistryUrl(originInvoker);

    //registry provider
    final Registry registry = getRegistry(originInvoker);
    final URL registeredProviderUrl = getRegisteredProviderUrl(originInvoker);

    //to judge to delay publish whether or not
    boolean register = registeredProviderUrl.getParameter("register", true);

    ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registeredProviderUrl);

    if (register) {
    
    
        /**
         * 2、这里是真正的服务注册的逻辑
         * registryUrl:是以zookeeper://ip:port
         * registeredProviderUrl:是以协议开头的,dubbo://ip:port
         *
         * 调用FailBackRegistry(这里要看配置的是哪种服务容错策略)
         */
        register(registryUrl, registeredProviderUrl);
        ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true);
    }

    // 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.
    //3、事件监听 待学习补充
    final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registeredProviderUrl);
    final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker);
    overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
    registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
    //Ensure that a new exporter instance is returned every time export
    return new DestroyableExporter<T>(exporter, originInvoker, overrideSubscribeUrl, registeredProviderUrl);
}

Servicio de red abierta

doLocalExport (originInvoker)
En este método, el método de exportación de dubboProtocol se llamará a través del mecanismo de extensión de spi. En el método de exportación, el servidor Netty se activará

La cadena de llamadas del siguiente método es así:

com.alibaba.dubbo.registry.integration.RegistryProtocol#export
	com.alibaba.dubbo.registry.integration.RegistryProtocol#doLocalExport
		com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol#export
			com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol#openServer
private void openServer(URL url) {
    
    
        // find server.
        String key = url.getAddress();
        //client can export a service which's only for server to invoke
        boolean isServer = url.getParameter(Constants.IS_SERVER_KEY, true);
        if (isServer) {
    
    
            ExchangeServer server = serverMap.get(key);
            if (server == null) {
    
    
                serverMap.put(key, createServer(url));
            } else {
    
    
                // server supports reset, use together with override
                server.reset(url);
            }
        }
    }

La lógica detrás del método createServer () no se describe en esta nota. Podemos pensar que createServer abre el servidor netty

Registro del centro de registro

En el com.alibaba.dubbo.registry.integration.RegistryProtocol#exportmétodo, el método doLocalExport () anterior se llamará primero para iniciar el servidor netty y luego ir al registro para registrar el servicio

@SPI("dubbo")
public interface RegistryFactory {
    
    

    @Adaptive({
    
    "protocol"})
    Registry getRegistry(URL url);
}

Al obtener el registro también se implementa a través del mecanismo SPI, por defecto es dubbo, tomamos zk como ejemplo, si el registro que configuramos es zk entonces se creará ZookeeperRegistry.

Entonces en

com.alibaba.dubbo.registry.integration.RegistryProtocol#export
	com.alibaba.dubbo.registry.integration.RegistryProtocol#register

De acuerdo con la url de registro para obtener la fábrica de registros actual, si es zk, entonces llamará

com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry#doRegister

@Override
    protected void doRegister(URL url) {
    
    
        try {
    
    
            /**
             * 这里的toUrlPath,最终会把路径转换为 dubbo/接口全类名/服务暴露的地址
             * 这里true,表示zk创建的是临时节点
             */
            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);
        }
    }

Puede ver aquí, el método zkClient.create () llamado directamente

El principio de exportación de dubbo es básicamente así. Después de la revisión del documento del sitio web oficial de dubbo, se proporciona un diagrama de secuencia de la exportación del servicio y la introducción del servicio en el sitio web oficial de dubbo
Inserte la descripción de la imagen aquí

Entonces, lo anterior es el principio básico de la exportación de servicios de Dubbo.

Supongo que te gusta

Origin blog.csdn.net/CPLASF_/article/details/113794622
Recomendado
Clasificación