三Dubbo服务暴露源码分析--3远程暴露-上

三Dubbo服务暴露源码分析--3远程暴露-上

3.2 远程暴露

image-20230313105805796

在Dubbo开发者手册中,给出了服务调用的流程图如上。其中,圈住部分为provider端的远程服务暴露部分的主流程。后续的分析,可以对照流程图,把握执行方向。

image-20230313105817381
ServiceConfig
 private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
/**……………………………………………………………………………………………………根据scope暴露服务(本地或远程)……………………………………………………………………………………………………………………… */
//TAG3.1.2.2. 暴露服务--scope
				//scope为null,需要暴露本地和远程服务(none:不暴露;remote:只远程;local:本地;null:本地+远程)
        String scope = url.getParameter(Constants.SCOPE_KEY);
        //配置为none不暴露(scope为none,不暴露服务;为null,或者其他,此处暴露)
        if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) { //1 

            //配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务)
            if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) { //2
//TAG1 本地暴露
                exportLocal(url);
            }//2
          
        /**……………………………………………………………………………远程暴露………………………………………………………………………………………………… */
            //如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露远程服务)
            if (! Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope) ){ //2
                if (logger.isInfoEnabled()) {
                    logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
                }
              //registry://localhost:2181/com.alibaba.dubbo.registry.RegistryService?application=demotest-provider&dubbo=2.5.3&organization=dubbox&owner=programmer&pid=25677&registry=zookeeper&timestamp=1671174564785
              //url为 dubbo://192.168.0.101:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demotest-provider&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=25677&side=provider&timestamp=1671174564948
                if (registryURLs != null && registryURLs.size() > 0
                        && url.getParameter("register", true)) { //3
                    for (URL registryURL : registryURLs) { //4
                      //从registryURL中获取参数,加入url中
                        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);
                        }
/** ……………………………………………………………………………………………………………………远程暴露……………………………………………………………………………………………………………………………………………………*/
//TAG1 registryURL.addParameterAndEncoded
//TAG2 proxyFactory@Adpative.getInvoker(ref)--ref转化为invoker
                        Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
//TAG3 protocol.export(invoker)--invoker转换为exporter
                        Exporter<?> exporter = protocol.export(invoker);
                      //将暴露出的服务,保存在serviceConfig的本地缓存lis<exporters>上
                        exporters.add(exporter);
                    }//4
                } //3
              else {
                    Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);

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

前面,已经执行完本地暴露。

TAG1 registryURL.addParameterAndEncoded
registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString());

TAG1/2主要会是向registry中注册暴露服务,因此,这里,把provider的服务" dubbo://192.168.0.101:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demotest-provider&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=25677&side=provider&timestamp=1671174564948",编码后加入registryURL的参数对parameters中,如下图所示。

image-20221218182737196

TAG2 proxyFactory@Adpative.getInvoker(ref)--ref转化为invoker

这里构造的过程,和本地暴露部分相同,详见3.1 本地暴露-TAG2部分。

在JavassistProxyFactory中构造abstractProxyInvoker匿名类,如下:

image-20221218183748755

此时invoker内URL为registry://localhost:2181,表示这时候的invoker需要去注册中心进行服务注册。

TAG3 Protocol$Adpative.export---invoker转换为exporter

image-20221218183428247

public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
    public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws RpcException {
        if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
      //registry://localhost:2181/com.alibaba.dubbo.registry.RegistryService?application=demotest-provider&dubbo=2.5.3&export=dubbo%3A%2F%2F192.168.0.101%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemotest-provider%26dubbo%3D2.5.3%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26methods%3DgetPermissions%26organization%3Ddubbox%26owner%3Dprogrammer%26pid%3D59337%26side%3Dprovider%26timestamp%3D1671361634513&organization=dubbox&owner=programmer&pid=59337&registry=zookeeper&timestamp=1671361634364
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
      //获取此时当前invoker.url的协议头为registry---表示这个invoker需要去注册中心执行注册
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
//TAG3.1 protocol自适应
        com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
//TAG3.2 protocol.export(listener->filter->registry)
        return extension.export(arg0);
    }
TAG3.1 protocol自适应

image-20221218185158860

image-20221218185222947

TAG3.2 protocol.export(listener->filter->registry)

此时,获取Protocol.class的拓展类,是个包装类,由外到内分别是listener->filter->registry。

EXP1 ProtocolListenerWrapper.export--注册服务
ProtocolListenerWrapper
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
  			//如果invoker.url的协议为registry,表示当前invoker服务需要注册到registry注册中心,因此不会真正暴露,而是直接执行
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }
  
  /**………………………………………………………………如果暴露的服务为 */
        return new ListenerExporterWrapper<T>(protocol.export(invoker), 
                Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
                        .getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
    }
EXP2 ProtocolFilterWrapper.export--
ProtocolFilterWrapper
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
  		//如果invoker.url的protocol协议为"registry",则表示是注册服务
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
          //直接执行registryProtocol.export
            return protocol.export(invoker);
        }
        return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
    }
EXP3 RegistryProtocol.export

RegistryProtocol类的初始化,在TAG3.1过程,(com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);的方法中,通过extensionLoader的构造和依赖注入功能,实例化并传入其属性完成初始化。

image-20221218205957701

参数:

originInvoker:
registry://localhost:2181/com.alibaba.dubbo.registry.RegistryService?application=demotest-provider&dubbo=2.5.3&export=dubbo%3A%2F%2F192.168.0.101%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemotest-provider%26dubbo%3D2.5.3%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26methods%3DgetPermissions%26organization%3Ddubbox%26owner%3Dprogrammer%26pid%3D59337%26side%3Dprovider%26timestamp%3D1671361634513&organization=dubbox&owner=programmer&pid=59337&registry=zookeeper&timestamp=1671361634364
RegistryProtocol
 
 public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
//EXP3.1 doLocalExport
  			//对服务dubbo://的暴露,并打开端口等操作
        final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);
//EXP3.2 getRegistry
  			//根据originInvoker的注册中心zookeeper://,加载registryService的实现类--zookeeperRegistry
        final Registry registry = getRegistry(originInvoker);
  			//获取注册的服务提供者的URL,即dubbo://
        final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);
//EXP3.3 registry.register
  			//将provider信息,注册到注册中心
        registry.register(registedProviderUrl);
  
/**…………………………………………………………………………………………………………override信息、overrideListener的订阅……………………………………………………………………………… */
        // 订阅override数据
        // FIXME 提供者订阅时,会影响同一JVM即暴露服务,又引用同一服务的的场景,因为subscribed以服务名为缓存的key,导致订阅信息覆盖。
  		//获取订阅的override数据
        final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registedProviderUrl);
  		//创建override监听器
        final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl);
        overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
  		//向注册中心订阅override
        registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
  
  
        //保证每次export都返回一个新的exporter实例(其包裹的exporter是EXP3.1doLocalExport中暴露的服务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);
                }
            }
        };
    }
/** …………暴露远程服务、打开端口……………*/
EXP3.1 doLocalExport--实际暴露远程服务、打开端口
originInvoker:
registry://localhost:2181/com.alibaba.dubbo.registry.RegistryService?application=demotest-provider&dubbo=2.5.3&export=dubbo%3A%2F%2F192.168.0.101%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemotest-provider%26dubbo%3D2.5.3%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26methods%3DgetPermissions%26organization%3Ddubbox%26owner%3Dprogrammer%26pid%3D59337%26side%3Dprovider%26timestamp%3D1671361634513&organization=dubbox&owner=programmer&pid=59337&registry=zookeeper&timestamp=1671361634364
RegistryProtocol    
  //本地缓存,记录providerURL暴露的exporter服务--避免暴露过的服务,不再重新暴露
      private final Map<String, ExporterChangeableWrapper<?>> bounds = new ConcurrentHashMap<String, ExporterChangeableWrapper<?>>();

private <T> ExporterChangeableWrapper<T>  doLocalExport(final Invoker<T> originInvoker){
//EXP3.1.1 getCacheKey(获取invoker在bounds中缓存的key)
        String key = getCacheKey(originInvoker);
  		//然后获取bounds内缓存的exporter---避免重复暴露
        ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
  
/**………………………………………………………………RegistryProtocol中bounds,记录是否暴露过服务………………………………………………………………………………………… */
        if (exporter == null) {
            synchronized (bounds) {//加锁
                exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
                if (exporter == null) {
//EXP3.1.2 InvokerDelegete
                    final Invoker<?> invokerDelegete = new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker));
//EXP3.1.3 protocol.export
//EXP3.1.4 ExporterChangeableWrapper
                    exporter = new ExporterChangeableWrapper<T>((Exporter<T>)protocol.export(invokerDelegete), originInvoker);
                    bounds.put(key, exporter);
                }
            }
        }
        return (ExporterChangeableWrapper<T>) exporter;
    }
//EXP3.1.1 getCacheKey(获取invoker在bounds中缓存的key)
    private String getCacheKey(final Invoker<?> originInvoker){
      //获取provider服务的url
        URL providerUrl = getProviderUrl(originInvoker);
      //移除参数--"dynamic", "enabled"用于在注册过程中
        String key = providerUrl.removeParameters("dynamic", "enabled").toFullString();
        return key;
    }
    
    	//通过invoker的url,获取provider的地址
        private URL getProviderUrl(final Invoker<?> origininvoker){
          //获取在registry://中添加入parameter的export:encode(providerURL),并解码
          //dubbo://192.168.0.101:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demotest-provider&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=59337&side=provider&timestamp=1671361634513
        String export = origininvoker.getUrl().getParameterAndDecoded(Constants.EXPORT_KEY);
        if (export == null || export.length() == 0) {
            throw new IllegalArgumentException("The registry export url is null! registry: " + origininvoker.getUrl());
        }
        //dubbo://192.168.0.101:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demotest-provider&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=59337&side=provider&timestamp=1671361634513
        URL providerUrl = URL.valueOf(export); //将string转换为URL
        return providerUrl;
    }

originInvoker内的相关数据----当前为注册服务的invoker。

image-20221219151646469

因此,getCacheKey,是获取originInvoker内参数providerURL(实际provider端的地址)。

//EXP3.1.2 InvokerDelegete->InvokerWrapper
//EXP3.1.2 InvokerDelegete
   final Invoker<?> invokerDelegete = new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker));

该过程,创建invoker与providerURL关联的委托类InvokerDelegete.

RegistryProtocol内部类

    public static class InvokerDelegete<T> extends InvokerWrapper<T>{
      //invokerdelegete委托类内保存真正的invoker
        private final Invoker<T> invoker;
       
        public InvokerDelegete(Invoker<T> invoker, URL url){
            super(invoker, url);
            this.invoker = invoker;
        }
      //getInvoker获取内部包裹的真正invoker
        public Invoker<T> getInvoker(){
            if (invoker instanceof InvokerDelegete){
                return ((InvokerDelegete<T>)invoker).getInvoker();
            } else {
                return invoker;
            }
        }
    }
public class InvokerWrapper<T> implements Invoker<T> {
    private final Invoker<T> invoker;
    private final URL url;
    public InvokerWrapper(Invoker<T> invoker, URL url){
        this.invoker = invoker;
        this.url = url;
    }

此时,构造成的invokerDelegete信息如下:

image-20221219153806751

作用:

因为此时,首先进行EXP3.1 doLocalExport暴露服务,尚未进行服务注册,因此在暴露过程中,把服务注册的invoker(registry://)和服务提供者providerURL(dubbo://)进行关联保存。

//EXP3.1.3 protocol@Adpative.export(invokerDelegete-->exporter转换)
//EXP3.1.3 protocol.export
//EXP3.1.4 ExporterChangeableWrapper
   exporter = new ExporterChangeableWrapper<T>((Exporter<T>)protocol.export(invokerDelegete), originInvoker);

继续跟进代码,执行invoker--》exporter操作

public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
    public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws RpcException {
        if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
      //invokerDelegete的URL为providerURL
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
      //providerurl协议为dubbo
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
        com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
//PTC1 protocol.export(listener->filter->dubbo)
        return extension.export(arg0);
    }

这里,根据invokerDelegete内providerurl的protocol协议,获取Protocol.class的拓展类。根据wrapper机制,会依次包裹listener、filter的协议类。

image-20221219155424524

这里的arg0,是invokerDelegete类。

PTC1 protocol.export(listener->filter->dubbo)--和本地暴露相同

这里protocol.export的暴露过程,和本地暴露基本相同,分别为暴露过程增加ExporterListener监听器、构建filter拦截器链。

ProtocolListenerWrapper
  public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }
  	//invoker.getUrl()协议头尾dubbo://,进行实际的远程暴露过程
        return new ListenerExporterWrapper<T>(protocol.export(invoker), 
                Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
                        .getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
    }
ProtocolFilterWrapper
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }
//PTC2 dubboProtocol.export
    	//invoker.getUrl()协议头尾dubbo://,进行实际的远程暴露过程
        return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
    }

在ProtocolFilterWrapper执行中,由于协议头是dubbo,不是registry,所以首先构造filter拦截器链。

image-20221219160236829

invoker链,为list构成的invoker链,尾部加上DelegeteInvoker的链。

image-20221219160559726

PTC2 dubboProtocol.export
DubboProtocol
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
  			//获取providerURL--dubbo://
        URL url = invoker.getUrl();
        
  			//com.alibaba.dubbo.demo.DemoService:20880 暴露服务的path:port
        String key = serviceKey(url);
//PTC2.1 DubboExporter
        DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);
  			//将dubbo://,DubboExporter的键值对存入map中
        exporterMap.put(key, exporter);
        
        //export an stub service for dispaching 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.put(url.getServiceKey(), stubServiceMethods);
            }
        }
//PTC2.2 openServer 打开服务端口
        openServer(url);
        
        return exporter;
    }
PTC2.1 DubboExporter
public class DubboExporter<T> extends AbstractExporter<T> {
    private final String                        key;
		//以dubbo://为key,DubboExporter为value的map,做缓存
    private final Map<String, Exporter<?>> exporterMap;

    public DubboExporter(Invoker<T> invoker, String key, Map<String, Exporter<?>> exporterMap){
        super(invoker);
        this.key = key;
        this.exporterMap = exporterMap;
    }

image-20221219161745873

存入map后,得到如下:

image-20221219162000216

PTC2.2 openServer 打开服务端口
DubboProtocol
    private final Map<String, ExchangeServer> serverMap = new ConcurrentHashMap<String, ExchangeServer>(); // <host:port,Exchanger>

    private void openServer(URL url) {
        //192.168.0.101:20880
        String key = url.getAddress();
        //client 也可以暴露一个只有server可以调用的服务。
        boolean isServer = url.getParameter(Constants.IS_SERVER_KEY,true);
        if (isServer) {
        	ExchangeServer server = serverMap.get(key);
        	if (server == null) {
//PTC2.2.1 createServer 创建ExchangeServer
//PTC2.2.2 DubboProtocol.serverMap.put(key, createServer(url))
        		serverMap.put(key, createServer(url));
        	} else {
        		//server支持reset,配合override功能使用
        		server.reset(url);
        	}
        }
    }
PTC2.2.1 createServer 创建ExchangeServer
DubboProtocol
 private ExchangeServer createServer(URL url) {
        //默认开启server关闭时发送readonly事件
        url = url.addParameterIfAbsent(Constants.CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString());
        //默认开启heartbeat
        url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT));
  			//获取远程服务端类型Netty
        String str = url.getParameter(Constants.SERVER_KEY, Constants.DEFAULT_REMOTING_SERVER);

        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, Version.isCompatibleVersion() ? COMPATIBLE_CODEC_NAME : DubboCodec.NAME);
        ExchangeServer server;
        try {
//PTC2.2.1.1 Exchangers.bind(url, requestHandler)-----返回HeaderExchangeServer
            server = Exchangers.bind(url, requestHandler);
        } catch (RemotingException e) {
            throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);
        }
        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;
    }
PTC2.2.1.1 Exchangers.bind(url, requestHandler)-BIND
//PTC2.2.1.1 Exchangers.bind(url, requestHandler)
            server = Exchangers.bind(url, requestHandler);

其中两个参数,

dubbo://192.168.0.101:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demotest-provider&channel.readonly.sent=true&codec=dubbo&dubbo=2.5.3&heartbeat=60000&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=73930&side=provider&timestamp=1671436924670

ExchangeHandler requestHandler,是服务端启动服务后,用于处理request请求的handler处理器。

posted @ 2023-03-13 14:41  LeasonXue  阅读(46)  评论(0编辑  收藏  举报