Dubbo导出服务之远程导出

 导出到远程入口

private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {

        /**
         * 前面的代码省略,从导出服务到远程的入口开始分析
         */

        //导出服务的scope,即决定服务导出到local还是远程
        String scope = url.getParameter(Constants.SCOPE_KEY);
        // don't export when none is configured
        // scope为none,则不导出
        if (!Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {

            // export to local if the config is not remote (export to remote only when config is remote)
            //为local则导出到local
            if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {
                exportLocal(url);
            }
            // export to remote if the config is not local (export to local only when config is local)
            //否则导出到远程
            if (!Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
                }
                //当注册url存在时
                if (registryURLs != null && !registryURLs.isEmpty()) {
                    for (URL registryURL : registryURLs) {
                        url = url.addParameterIfAbsent(Constants.DYNAMIC_KEY, registryURL.getParameter(Constants.DYNAMIC_KEY));
                        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);
                        }

                        // For providers, this is used to enable custom proxy to generate invoker
                        String proxy = url.getParameter(Constants.PROXY_KEY);
                        if (StringUtils.isNotEmpty(proxy)) {
                            registryURL = registryURL.addParameter(Constants.PROXY_KEY, proxy);
                        }

                        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);
                        exporters.add(exporter);
                    }
                } else {
                    Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
                    DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);

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

    }

 

导出服务

/**
     * 导出服务到远程其中的一步:导出服务
     * 在com.alibaba.dubbo.registry.integration.RegistryProtocol类中
     * @param originInvoker
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    private <T> RegistryProtocol.ExporterChangeableWrapper<T> doLocalExport(final Invoker<T> originInvoker) {
        //获取key
        String key = getCacheKey(originInvoker);
        /**
         * 根据key值去bounds中去获取缓存
         * bounds是一个ConcurrentHashMap<String, ExporterChangeableWrapper>
         */
        ExporterChangeableWrapper<T> exporter = (RegistryProtocol.ExporterChangeableWrapper<T>) bounds.get(key);
        //双重检查锁
        if (exporter == null) {
            synchronized (bounds) {
                /**
                 * 如果从缓存bounds中获取不到则new一个InvokerDelegete对象,
                 * 并将其包装成ExporterChangeableWrapper对象并存储到缓存中,
                 * 最后返回从缓存中获取到的或者新创建的exporter
                 */
                exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
                if (exporter == null) {
                    final Invoker<?> invokerDelegete = new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker));
                     /**
                     * protocol指com.alibaba.dubbo.rpc.Protocol接口,
                     * 此处的实现类是根据采用的协议来选取的
                     * 如果协议为dubbo,则实现类为DubboProtocol
                     * 即通过dubbo协议进行服务的导出
                     */
                    exporter = new ExporterChangeableWrapper<T>((Exporter<T>) protocol.export(invokerDelegete), originInvoker);
                    bounds.put(key, exporter);
                }
            }
        }
        return exporter;
    }

 根据不同的协议导出服务,以dubbo举例

/**
     * 当使用协议为dubbo时,使用此方法进行服务的导出
     * 此方法是在com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol类中
     * @param invoker
     * @param <T>
     * @return
     * @throws RpcException
     */
    @Override
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        /**
         * invoker为调用者
         * 从invoker中获取对应的url
         */
        URL url = invoker.getUrl();

        // export service.
        /**
         * 调用serviceKey方法拼接服务组名、服务名、服务版本、服务端口
         * 在获取服务端口时,如果没有回取默认值
         */
        String key = serviceKey(url);
        /**
         * 创建DubboExporter导出者
         * exporterMap是一个缓存map,存放的数据为Exporter导出者
         */
        DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);
        exporterMap.put(key, exporter);

        //export an stub service for dispatching event
        //本地存根相关代码
        Boolean isStubSupportEvent = url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT);
        Boolean isCallbackservice = url.getParameter(Constants.IS_CALLBACK_SERVICE, false);
        if (isStubSupportEvent && !isCallbackservice) {
            String stubServiceMethods = url.getParameter(Constants.STUB_EVENT_METHODS_KEY);
            if (stubServiceMethods == null || stubServiceMethods.length() == 0) {
                if (logger.isWarnEnabled()) {
                    logger.warn(new IllegalStateException("consumer [" + url.getParameter(Constants.INTERFACE_KEY) +
                            "], has set stubproxy support event ,but no stub methods founded."));
                }
            } else {
                /**
                 * 如果存根服务方法存在,则存入缓存stubServiceMethodsMap中
                 * stubServiceMethodsMap是一个ConcurrentHashMap
                 * private final ConcurrentMap<String, String> stubServiceMethodsMap = new ConcurrentHashMap<String, String>();
                 */
                stubServiceMethodsMap.put(url.getServiceKey(), stubServiceMethods);
            }
        }

        //启动服务器
        openServer(url);
        //优化序列化
        optimizeSerialization(url);
        return exporter;
    }

 启动服务器

/**
     * 开启服务器
     * @param url
     */
    private void openServer(URL url) {
        // find server.
        String key = url.getAddress();
        //client can export a service which's only for server to invoke
        /**
         * 检查client是否能导出该服务
         */
        boolean isServer = url.getParameter(Constants.IS_SERVER_KEY, true);
        if (isServer) {
            /**
             * 首先从缓存serverMap中获取ExchangeServer
             * serverMap是一个ConcurrentHashMap类型的容器
             * private final Map<String, ExchangeServer> serverMap = new ConcurrentHashMap<String, ExchangeServer>()
             */
            ExchangeServer server = serverMap.get(key);
            if (server == null) {
                //如果server不存在,则调用createServer创建一个服务器实例并存入缓存
                serverMap.put(key, createServer(url));
            } else {
                // server supports reset, use together with override
                //如果server存在,需要进行重置
                server.reset(url);
            }
        }
    }

创建服务器实例

/**
     * 创建服务器实例
     * @param url
     * @return
     */
    private ExchangeServer createServer(URL url) {
        // send readonly event when server closes, it's enabled by default
        //添加服务器关闭时默认发送只读事件配置到url中
        url = url.addParameterIfAbsent(Constants.CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString());
        // enable heartbeat by default
        //添加心跳检测配置到url中
        url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT));
        /**
         * 获取server参数,默认为netty
         * 此处的String str变量在接下来会被多次赋值,
         * 主要起一个临时变量的作用
         */
        String str = url.getParameter(Constants.SERVER_KEY, Constants.DEFAULT_REMOTING_SERVER);

        //通过SPI机制获取Transporter接口的实现类并检测其中是否包含str所代表的的实现类,如果没有则抛异常
        if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str))
            throw new RpcException("Unsupported server type: " + str + ", url: " + url);

        //添加编码解码器参数
        url = url.addParameter(Constants.CODEC_KEY, DubboCodec.NAME);
        /**
         * 创建ExchangeServer实例
         */
        ExchangeServer server;
        try {
            server = Exchangers.bind(url, requestHandler);
        } catch (RemotingException e) {
            throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);
        }
        /**
         * 获取client参数,然后通过SIP检测支持的类型中是否包含此类型,如果不包含则抛异常
         */
        str = url.getParameter(Constants.CLIENT_KEY);
        if (str != null && str.length() > 0) {
            Set<String> supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions();
            if (!supportedTypes.contains(str)) {
                throw new RpcException("Unsupported client type: " + str);
            }
        }
        return server;
    }

 创建服务器实例续

/**
     * 创建服务器实例
     * @param url
     * @param handler
     * @return
     * @throws RemotingException
     */
    public static ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
        if (url == null) {
            throw new IllegalArgumentException("url == null");
        }
        if (handler == null) {
            throw new IllegalArgumentException("handler == null");
        }
        url = url.addParameterIfAbsent(Constants.CODEC_KEY, "exchange");
        /**
         * getExchanger()获取交换机,默认获取为header=com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchanger
         */
        return getExchanger(url).bind(url, handler);
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值