• dubbo源码分析二:服务发布


        本文将深入分析dubbo的服务发布涉及到的流程及主要类的代码。首先,我们先从类的关系图来看一下dubbo发布服务涉及到的相关类。

    1.类图

       上图展示了部分服务发布过程中需要使用到的类和接口,其中:

        spring适配涉及到的类:DubboNamespaceHandler、DubboBeanDefinitionParser、ServiceBean;

        配置信息存储:ServicdConfig、RegistryConfig、MonitorConfig、ProtocolConfig、ProviderConfig等;

        应用协议:Protocol、DubboProtocol、HessianProtocol、ThriftProtocol、RmiProtocol、AbstractProxyProtocol、AbstractProtocol等;

        Server相关:Exchanger、HeaderExchanger、ExchangeServer、HeaderExchangeServer、Transporters、Transporter、NettyTransporter、NettyServer等;

    2.时序图

        我们通过时序图来分析一下在发布服务的过程中,上面的类是如何串联在一起的:

        a.spring容器通过DubboBeanDefinitionParser类的对象来解析xml文件中的标签,生成ServiceConfig等配置对象;

        b.ServiceConfig的export()等发布服务的方法被调用;

        c.通过spi机制确定Protocol接口的实现对象为DubboProtocol的对象,调用它的openServer()等方法;

        d.通过spi机制确定Transporter接口的实现对象为NettyTransporter,调用它的bind()方法;

        e.调用NettyServer类,启动netty服务,绑定端口。

     3.核心代码解析

    a.DubboProtocol

        public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
            URL url = invoker.getUrl();//获取url信息
            
            // export service.
            String key = serviceKey(url);//产生与发布的接口映射的key ,格式例如:com.alibaba.dubbo.demo.DemoService:20882
            DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);//创建DubboExporter对象
            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);
                }
            }
    
            openServer(url);//打开服务
            
            return exporter;
        }
        
        private void openServer(URL url) {
            // find server.
            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) {
            		serverMap.put(key, createServer(url));//创建新的服务
            	} else {
            		//server支持reset,配合override功能使用
            		server.reset(url);
            	}
            }
        }
        
        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));
            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 {
                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;
        }
    

      b.NettyServer

        protected void doOpen() throws Throwable {
            NettyHelper.setNettyLoggerFactory();
            ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));//boss线程池
            ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));//工作线程池
            ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS));
            bootstrap = new ServerBootstrap(channelFactory);//服务启动类
            
            final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
            channels = nettyHandler.getChannels();
            // https://issues.jboss.org/browse/NETTY-365
            // https://issues.jboss.org/browse/NETTY-379
            // final Timer timer = new HashedWheelTimer(new NamedThreadFactory("NettyIdleTimer", true));
            bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
                public ChannelPipeline getPipeline() {
                    NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec() ,getUrl(), NettyServer.this);
                    ChannelPipeline pipeline = Channels.pipeline();
                    /*int idleTimeout = getIdleTimeout();
                    if (idleTimeout > 10000) {
                        pipeline.addLast("timer", new IdleStateHandler(timer, idleTimeout / 1000, 0, 0));
                    }*/
                    pipeline.addLast("decoder", adapter.getDecoder());//增加解码器
                    pipeline.addLast("encoder", adapter.getEncoder());//增加编码器
                    pipeline.addLast("handler", nettyHandler);//业务处理类
                    return pipeline;
                }
            });
            // bind
            channel = bootstrap.bind(getBindAddress());
        }
    

      

  • 相关阅读:
    odoo14系列笔记-基本进销存(二)
    odoo14系列笔记-基本进销存(一)
    PVE另一种方法使用中科大的镜像服务器 NGINX反向代理
    git 国内加速
    VirtualBox开启套娃模式-打开嵌套 VT-x/AMD-V 功能
    K8S集群安装(基于DEIBAN,proxmox)
    JS语法 ES6、ES7、ES8、ES9、ES10、ES11、ES12新特性
    8个非常实用的Vue自定义指令
    require和import的区别
    js异步加载之defer、async、type=module
  • 原文地址:https://www.cnblogs.com/mantu/p/6003901.html
Copyright © 2020-2023  润新知