iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >DUBBO服务启动过程
  • 719
分享到

DUBBO服务启动过程

2023-06-05 06:06:22 719人浏览 薄情痞子
摘要

dubbo的启动主要是发布服务的过程,起到核心作用的就是ServiceConfig(ServiceConfig就是我们在Dubbo的配置文件中配置的dubbo:service这些配置项对应的实体类)。服务的启动初始位置也基本是在这里,下面我

dubbo的启动主要是发布服务的过程,起到核心作用的就是ServiceConfig(ServiceConfig就是我们在Dubbo的配置文件中配置的dubbo:service这些配置项对应的实体类)。服务的启动初始位置也基本是在这里,下面我们来看看具体的实现内容。

讲基本内容前首先理清楚几个名词概念:

Invoker:Invoker的概念我们在动态代理的时候就接触过,中文的意思大概是执行者,这里其实可以理解为具体方法的执行者。其核心内容大致如下:

  1. Class<T> getInterface();

  2. Result invoke(Invocation invocation) throws rpcException;

  3. URL getUrl();
     

通过以上的三个方法们就可以执行到具体的方法并且获得方法的执行结果。通过getUrl获得需要执行的方法具体实现细节,主要是获得具体的ref;其次就是组装方法的参数信息等等,这些信息在invocation里面都有封装;最后通过执行invoke方法触发具体的方法并返回结果。从这里可以看出Invoker是具体方法执行的最后一个守关者,获得了Invoker,就获得了具体接口的代码,然后执行代理就可以。

Invoker仅仅是作为一个代理的门面,其不仅可以代表本地执行Duubo调用的代理,还可以充当RPC时候的代理,更是可以将自己包装成一个多个Invoker聚合而成的代理(主要是处理集群的一些策略,包括负载均衡和路由等)。

Exporter:服务暴露的过程中会将Invoker转换成Exporter(暴露者),及Exporter其实包含了Invoker,主要是用于不同层面的服务发布。
其实Dubbo 还有一些比较重要的对象,像Protocol,Exchanger等等。我认为在这里直接说明不太合适,所以等到我们用到之后再开始说明。

1. 核心的属性信息

一些基本的属性:group,version,interfaceName,interfaceClass,timeout等等。我们凡是可以在dubbo:service上配置的属性都在ServiceConfig中可以找得到对应的属性;

//dubbo对应的服务发布协议,这里可以清楚地看到Dubbo在这里使用的自己的spi机制,来保证灵活性。(至于SPI机制的具体实现,之后有机会的话会讲到,简单理解就是通过getExtensionLoader获得对应类的扩展类实现类)

private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();

private final List<URL> urls = new ArrayList<URL>();
private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();

2.服务暴露过程

对于服务暴露来说,在ServiceConfig里面的初始方法就是export()方法了,下面我们从export方法开始来看看:

public synchronized void export() {        if (provider != null) {            //默认取provider的配置            if (export == null) {                export = provider.getExport();            }            if (delay == null) {                delay = provider.getDelay();            }        }        //如果export设置为false的话就直接返回        if (export != null && ! export.booleanValue()) {            return;        }        //如果设置延迟时间的话就延迟指定时间然后进行暴露        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(); //一切暴露的核心还都是要看doExport方法。        }    }         protected synchronized void doExport() {        // 防止服务多次暴露                 // 设置默认的基本属性                 // 针对泛化接口做单独处理        if (ref instanceof GenericService) {            interfaceClass = GenericService.class;            if (StringUtils.isEmpty(generic)) {                generic = Boolean.TRUE.toString();            }        } else {            try {//通过反射初始化接口(interfaceName是实现类的全称)                interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()                        .getContextClassLoader());            } catch (ClassNotFoundException e) {                throw new IllegalStateException(e.getMessage(), e);            }            //检查定义的方法是否为接口中的方法            checkInterfaceAndMethods(interfaceClass, methods);            //检查引用不为空,并且引用必需实现接口            checkRef();            //如果到这一步的话说明类实现是自己定义的,所以设置generic为false            generic = Boolean.FALSE.toString();        }                 // 处理Local和Stub代理处理                 // 检查Application,ReGIStry,Protocol的配置情况                 //将配置的属性绑定到当前对象        appendProperties(this);                 //针对Local,Stub和Mock进行校验                 //上面的操作主要是做一些检验和初始化的操作,没有涉及到具体的暴露服务逻辑                 doExportUrls();    }         private void doExportUrls() {        //取到注册中心的URL        List<URL> registryURLs = loadRegistries(true);        for (ProtocolConfig protocolConfig : protocols) {            //根据配置的通信协议将服务暴露到注册中心            doExportUrlsFor1Protocol(protocolConfig, registryURLs);        }    }         private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {                 //  默认采用Dubbo协议                 //之后的部分逻辑就是想尽一切办法取到host                 //取到端口号(之后的部分关于端口的逻辑就是想尽一切办法取端口号)                 // 这个map十分重要,它的意义在于所有存储所有最终使用到的属性,我们知道一个属性例如timeout,可能在Application,provider,service中都有配置,具体以哪个为准,都是这个map处理的事情。        Map<String, String> map = new HashMap<String, String>();        if (anyhost) { //如果此时anyhost为true的话            map.put(Constants.ANYHOST_KEY, "true");        }        // 存储简单的服务信息                 //将application,module,provider,protocol和service的信息设置到map里面        //将应用配置的树勇按照层级存入map中。注意这里的层级关系,是一层层覆盖的 即关系为:ServiceConfig->PrtocolConfig->ProviderConfig->ModuleConfig->ApplicaionConfig                 //单独处理好method层级的参数关系                 //判断有没有配置通配协议        if (ProtocolUtils.isGeneric(generic)) {            map.put("generic", generic);            map.put("methods", Constants.ANY_VALUE);        } else {            String revision = Version.getVersion(interfaceClass, version);            if (revision != null && revision.length() > 0) {                map.put("revision", revision);            }            //通过包装类将interfaceClass进行包装然后取得方法名字,对于wapper包装器就是将不同的类统一化            //参考Http://blog.csdn.net/quhongwei_zhanqiu/article/details/41597261理解Wapper            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();            if(methods.length == 0) {                logger.warn("NO method found in service interface " + interfaceClass.getName());                map.put("methods", Constants.ANY_VALUE);            }            else {                //将所有的方法拼接成以逗号为分隔符的字符串                map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));            }        }        //处理token属性                 //如果配置的inJVM的话就代表本地调用(本地调用还用Dubbo的话实在有点蛋疼)                 //所有的核心属性最后都成了URL的拼接属性,如果我们还记得map里面拼装了多少属性的话就知道这个URL内容有多丰富        URL url = new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + path, map);                          // 下面是核心暴露过程,将不会省略源码        String scope = url.getParameter(Constants.SCOPE_KEY);        //配置为none不暴露        if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {             //配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务)            if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {                exportLocal(url);            }            //如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露远程服务)            if (! Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope) ){                if (logger.isInfoEnabled()) {                    logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);                }                if (registryURLs != null && registryURLs.size() > 0                        && url.getParameter("register", true)) {                    for (URL registryURL : registryURLs) {                        //dynamic表示是否需要人工管理服务的上线下线(动态管理模式)                        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);                        }                       ====================================================                       //取到invoker对象(ref为接口实现类的引用)                        Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));                        //将invoker转化为exporter对象                        Exporter<?> exporter = protocol.export(invoker);                        exporters.add(exporter); //将exporter添加到需要暴露的列表中取                    }                    ================================================================                } else {                    //如果找不到注册中心的话就自己充当自己的注册中心吧                    Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);                     Exporter<?> exporter = protocol.export(invoker);                    exporters.add(exporter);                }            }        }        //多个协议就有多个url与其对应,所以要一一存储。        this.urls.add(url);    }
通过ServicConfig中的内容分解,我们看出来里面主要做的内容如下:
  • 检验所需参数的合法性

  • 将多层的参数(可能重复配置)最终整理出最终的结果(map),然后根据参数拼接成暴露服务需用到的url。

  • 处理generic,Stub,injvm等其他需要支持的内容,补充dubbo的功能多样性,但是都不涉及核心流程。

  • 根据对应的协议将服务进行暴露(将提供的服务推送到注册中心供服务调用者发现),默认使用Dubbo协议。

--结束END--

本文标题: DUBBO服务启动过程

本文链接: https://www.lsjlt.com/news/241617.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • DUBBO服务启动过程
    Dubbo的启动主要是发布服务的过程,起到核心作用的就是ServiceConfig(ServiceConfig就是我们在Dubbo的配置文件中配置的dubbo:service这些配置项对应的实体类)。服务的启动初始位置也基本是在这里,下面我...
    99+
    2023-06-05
  • Dubbo的服务引用过程是什么
    这篇文章主要讲解了“Dubbo的服务引用过程是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Dubbo的服务引用过程是什么”吧!服务引用大致流程我们已经...
    99+
    2024-04-02
  • 基于Docker部署Dubbo+Nacos服务的过程
    目录一、说明二、部署 Nacos 注册中心三、部署 Dubbo 服务3.1. 部署 provider 服务3.2. 部署 consumer 服务四、样例工程 一、说明 本文介绍基于 ...
    99+
    2023-02-27
    Docker部署Dubbo+Nacos服务 Docker部署Dubbo Docker部署Nacos服务
  • dubbo服务注册到nacos的过程剖析
    目录前言简述过程源码剖析具体实现服务注册服务订阅结语前言 前面聊到到了我们的dubbo服务从redis迁移到nacos注册中心,迁移后发现,会时不时的抛一个异常 ERROR...
    99+
    2024-04-02
  • 详解Android壁纸服务的启动过程
    壁纸基础 android中的壁纸分为动态壁纸和静态壁纸两种,两种类型的壁纸都以Service的类型运行在系统后台。 静态壁纸:仅以图片的形式进行展示对于静态壁纸,可以使用W...
    99+
    2024-04-02
  • Android系统启动(四) — Launcher 启动过程
    1 Launcher 概述 系统启动的最后一步是启动一个应用程序来显示系统中已经安装的应用程序,这个应用程序就叫做 Launcher。Launcher 在启动过程中会请求 PackageManager...
    99+
    2023-09-04
    android java 开发语言
  • Tomcat服务器的配置与启动全过程
    目录Tomcat的下载与安装关于Tomcat服务器的目录startup.bat部分代码catalina.bat部分代码Tomcat服务器的运行最终步骤解决Tomcat服务器启动时在D...
    99+
    2023-03-20
    Tomcat服务器配置 Tomcat服务器启动 Tomcat服务器
  • mysql5.7单实例自启动服务配置过程
    1.mysql版本 [root@clq system]# mysql -v Welcome to the MySQL monitor. Commands end with ; ...
    99+
    2024-04-02
  • Dubbo+zookeeper搭配分布式服务的过程详解
    目录分布式架构: Dubbo 是什么Dubbo:思想:依赖:分布式架构:  1.当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐...
    99+
    2024-04-02
  • MySQL8.0服务无法正常启动的解决过程
    目录mysql8服务无法正常启动的解决(1053错误)第一种方法第二种方法MySQL8服务无法正常启动的解决(1069错误)MySQL8.0 服务无法启动 3534总结一下MySQL8服务无法正常启动的解决(1053错误...
    99+
    2022-12-26
    MySQL8.0 MySQL8.0无法启动 无法启动MySQL8.0服务
  • mysql中innodb的启动过程
    这篇文章主要讲解了“mysql中innodb的启动过程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mysql中innodb的启动过程”吧!fil_init...
    99+
    2024-04-02
  • solaris学习3:启动过程
       #---------- ADDED BY BOOTADM - DO NOT EDIT ---------- title Oracle Solaris 10 8/11 s10x_u10wos_17b X86 find...
    99+
    2023-01-31
    过程 solaris
  • Android Activity启动过程详解
     Android系统启动篇 1,《android系统启动流程简介》 2,《android init进程启动流程》 3,《android zygote进程启动流程》 4,《Android SystemServer进程启动流程》 5,《andr...
    99+
    2023-09-02
    android
  • 教你springboot+dubbo快速启动的方法
    目录前言实操测试前言 现在用dubbo的太多了,我到现在还不熟悉,这太不应该了,这次好好看了一下dubbo,终于把基本的启动框架搭好了。dubbo的角色宽泛的分三类provider,...
    99+
    2024-04-02
  • java开发分布式服务框架Dubbo暴露服务过程详解
    目录Dubbo服务暴露机制前言服务暴露流程源码解析本地暴露远程暴露Dubbo服务暴露机制 前言 在进行服务暴露机制的分析之前,必须谈谈什么是URL,在Dubbo服务暴露过程中URL是...
    99+
    2024-04-02
  • java开发分布式服务框架Dubbo调用过程
    目录大致流程调用请求的具体信息协议Dubbo协议序列化器调用流程图调用流程源码分析——客户端模板方法模式路由和负载均衡调用的三种方式调用流程源码分析——服务端总结大致流程 客户端根据...
    99+
    2024-04-02
  • java开发分布式服务框架Dubbo服务引用过程详解
    目录大致流程服务引用策略服务引用的三种方式服务引入流程解析总结大致流程 Provider将服务暴露出来并且注册到注册中心,而Consumer通过注册中心获取Provider的信息,之...
    99+
    2024-04-02
  • 详解Android系统启动过程
    目录计算机是如何启动的引导阶段加载内核阶段Android的启动过程init进程init.rc 文件service_manager 进程surface_flinger 进程media_...
    99+
    2024-04-02
  • Springboot详解底层启动过程
    目录SpringApplication构造分析SpringApplication run分析SpringApplication构造分析 1、记录 BeanDefinition 源 s...
    99+
    2024-04-02
  • mysql安装过程启动服务器失败怎么解决
    在MySQL安装过程中启动服务器失败可能是由于多种原因造成的,可以尝试以下方法来解决问题: 检查日志文件:查看MySQL的错误日...
    99+
    2024-04-20
    mysql 服务器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作