Dubbo概述

dubbo框架提供多协议远程调用,服务提供方可以是分布式部署。dubbo框架可以很简单的帮我们实现微服务。

此处援引官网上图片

dubbo分为客户端和服务提供方

服务方将服务注册到注册中心

客户端从注册中心获取已注册服务访问方式

客户端通过指定协议访问服务提供方

根据dubbo架构,源码分析我们主要切入点是:

  1. dubbo配置如何生效
  2. 客户端如何调用服务
  3. 注册的服务如何保证被调用到
  4. dubbo远程调用的协议如何工作

针对以上我们来分析Dubbo源码:

Dubbo源码是maven管理,工程主要由dubbo-config,dubbo-container,dubbo-filter,dubbo-monitor,dubbo-registry,dubbo-remoting,dubbo-rpc,dubbo-serialization组成。

  • dubbo-config :dubbo配置文件相关模块
  • dubbo-container :dubbo依赖的上下文
  • dubbo-filter : dubbo支持的请求过滤器
  • dubbo-monitor : dubbo监控管理模块
  • dubbo-registry : dubbo使用注册中心相关的模块
  • dubbo-remoting : dubbo整个远程交互框架,如何将通道、序列化、通信载体有机整合
  • dubbo-rpc : dubbo远程调用协议实现。
  • dubbo-serialization : 远程通信中序列化实现

dubbo配置加载

dubbo配置是以松耦合的方式嵌入到spring里面,因此说到dubbo配置加载就必然和spring扯不开关系。

从dubbo配置文件的命名空间说起,我们通常在配置dubbo服务时要在spring配置基础上添加dubbo的命名空间(xmlns)和模板:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

  

xmlns:dubbo的值指定了dubbo配置命名空间。
spring中不同的命名空间对应不同的配置解析器,那么dubbo的命名空间http://code.alibabatech.com/schema/dubbo也就对应着自己的解析器。
spring维护着命名空间和对应解析器的关系,这些对应关系包括spring内置的和第三方定制关系

spring命名空间

spring启动中解析dubbo xml文件时首先获取跟节点中的所有xmlns值,根据配置的命名空间从命名空间管理器中获取该空间对应的解析器对象

命名空间管理器会从classpath下META-INF/下加载并解析所有的所有spring.handlers命名的文件,该文件以键值对配置了命名空间和对应解析器。

dubbo的命名spring.handler配置如下:

http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

路径:META-INF/dubbo/spring.handler

如此,spring在加载dubbo配置时会调用dubbo命名空间解析器DubboNamespaceHandler来解析配置文件,dubbo的入口也就是DubboNamespaceHandler。

dubbo配置解析处理器(DubboNamespaceHandler)

dubbo配置解析处理器就是命名空间配置的com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler,该处理器作为dubbo对spring的扩展完成dubbo自定义的配置解析工作。spring的命名空间处理器扩展点是:org.springframework.beans.factory.xml.NamespaceHandlerSupport,DubboNamespaceHandler完成dubbo内部所有解析器初始和加载。解析器包括application节点解析、module节点解析、registry、monitor、provider、consumer、protocol、service、reference、annotation。

这些解析器初始化代码如下:

 public void init() {
registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
}

DubboNamespaceHandler做了什么

spring加载配置文件过程中,读取到一个xml节点时,会将节点信息传递给DubboNamespaceHandler,handler获取节点的LocalName(在一个命名空间下去掉前缀剩下的节点名          称),根据名称从DubboNamespaceHandler获取对应的Parser,如:LocalName是application,就会获取到Handler初始化时注册的application对应的                                                    DubboBeanDefinitionParser对象,并调用该解析器的parse方法将节点转换成spring的RootBeanDefinition对象,对象保存了创建一个bean对象所需的所有信 息。

Dubbo服务(ServiceBean)

通过registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));注册的DubboBeanDefinitionParser

创建出的RootBeanDefinition最终被spring实例化成ServiceBean,ServiceBean即Dubbo实际的服务实例。实例化结束后,ServiceBean会从spring容器中获取配置的Provider信         息、application、module、registry、monitor、protocol等配置信息并设置到ServiceBean,设置完成后将服务自身暴露出去,如果本次暴露失败或者没有暴露,则在spring容器启       动完成后会再进行一次暴露。

服务暴露

服务暴露通过调用ServiceBean的export方法,通过注册中心,最终将服务实例以指定的协议暴露给调用方。

准备暴露路径

服务暴露前需要组织自己的访问路径和协议信息,只有有了这些信息,才能确定以何种协议被访问,以及通过什么路径被访问。组织访问信息的方法是服务自身的doExportUrls

ServiceConfig.doExportUrls()

     private void doExportUrls() {
List<URL> registryURLs = loadRegistries(true);
for (ProtocolConfig protocolConfig : protocols) {
doExportUrlsFor1Protocol(protocolConfig, registryURLs);
}
}

该方法调用了doExportUrlsFor1Protocol方法将协议和注册路径具体的组装起来,形成dubbo的访问路径,将访问路径包装成可被远程调用的调用器invoker。

invoker的生成代码如下:

             //如果配置不是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) {
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<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString())); Exporter<?> exporter = protocol.export(invoker);
exporters.add(exporter);
}
} else {
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url); Exporter<?> exporter = protocol.export(invoker);
exporters.add(exporter);
}
}
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
参数ref指向的是dubbo:service配置中ref中指定的服务对象,interfaceClass是该服务的接口,第三个参数则是该服务的访问路径。
Exporter<?> exporter = protocol.export(invoker);   // 最终将invoker暴露

Dubbo学习-源码学习的更多相关文章

  1. python 协程库gevent学习--源码学习(一)

    总算还是要来梳理一下这几天深入研究之后学习到的东西了. 这几天一直在看以前跟jd对接的项目写的那个gevent代码.为了查错,基本上深入浅出了一次gevent几个重要部件的实现和其工作的原理. 这里用 ...

  2. Dubbo源码学习--服务是如何引用的

    ReferenceBean 跟服务引用一样,Dubbo的reference配置会被转成ReferenceBean类,ReferenceBean实现了InitializingBean接口,直接看afte ...

  3. Dubbo源码学习--注册中心分析

    相关文章: Dubbo源码学习--服务是如何发布的 Dubbo源码学习--服务是如何引用的 注册中心 关于注册中心,Dubbo提供了多个实现方式,有比较成熟的使用zookeeper 和 redis 的 ...

  4. Dubbo源码学习--服务是如何发布的

    相关文章: Dubbo源码学习--服务是如何发布的 Dubbo源码学习--服务是如何引用的 ServiceBean ServiceBean 实现ApplicationListener接口监听Conte ...

  5. Dubbo源码学习--集群负载均衡算法的实现

    相关文章: Dubbo源码学习文章目录 前言 Dubbo 的定位是分布式服务框架,为了避免单点压力过大,服务的提供者通常部署多台,如何从服务提供者集群中选取一个进行调用, 就依赖Dubbo的负载均衡策 ...

  6. Dubbo源码学习文章目录

    目录 Dubbo源码学习--服务是如何发布的 Dubbo源码学习--服务是如何引用的 Dubbo源码学习--注册中心分析 Dubbo源码学习--集群负载均衡算法的实现

  7. Dubbo源码学习--优雅停机原理及在SpringBoot中遇到的问题

    Dubbo源码学习--优雅停机原理及在SpringBoot中遇到的问题 相关文章: Dubbo源码学习文章目录 前言 主要是前一阵子换了工作,第一个任务就是解决目前团队在 Dubbo 停机时产生的问题 ...

  8. Dubbo源码学习总结系列一 总体认识

    本文写作时,dubbo最高版本是V2.6.0.  写这篇文章主要想回答以下4个问题: 一.dubbo是什么?完成了哪些主要需求? 二.dubbo适用于什么场景? 三.dubbo的总体架构是什么样的? ...

  9. Dubbo源码学习(二)

    @Adaptive注解 在上一篇ExtensionLoader的博客中记录了,有两种扩展点,一种是普通的扩展实现,另一种就是自适应的扩展点,即@Adaptive注解的实现类. @Documented ...

随机推荐

  1. 【Mac】Mac OS X 安装GNU命令行工具

    macos的很多用户都是做it相关的人,类unix系统带来了很多方面,尤其是经常和linux打交道的人. 但是作为经常使用linux 命令行的人发现macos中的命令行工具很多都是bsd工具,跟lin ...

  2. 2016 苹果全球开发者大会(WWDC)

    纵观WWDC 2016开发者大会的全部内容,尽管本次大会没有那些新的产品发布,不过能让各位果粉的肾留到秋天,那也是苹果公司对各位果粉的关爱啊.但是对iOS开发者而言,新发布的技术还是比较不错的.主要内 ...

  3. Linux Android 多点触摸协议 原文出自【比特网】,转载请保留原文链接:http://soft.chinabyte.com/os/71/12306571.shtml

    为了使用功能强大的多点触控设备,就需要一种方案去上报用户层所需的详细的手指触摸数据.这个文档所描述的多点触控协议可以让内核驱动程序向用户层上报任意多指的数据信息. 使用说明 单点触摸信息是以ABS承载 ...

  4. Linux进程实践(1) --Linux进程编程概述

    进程 VS. 程序 什么是程序? 程序是完成特定任务的一系列指令集合. 什么是进程? [1]从用户的角度来看:进程是程序的一次执行过程 [2]从操作系统的核心来看:进程是操作系统分配的内存.CPU时间 ...

  5. android 自定义下拉菜单

    本实例的自定义下拉菜单主要是继承PopupWindow类来实现的弹出窗体,各种布局效果可以根据自己定义设计.弹出的动画效果主要用到了translate.alpha.scale,具体实现步骤如下: 先上 ...

  6. 【Qt编程】Qt学习之状态栏

    QStatusBar类提供一个水平条来显示状态信息.所谓状态信息,拿个简单的例子来说,当你在word中编辑时,左下角就会出现页面.字数等等信息.状态信息可以分为三类:临时信息,如一般的提示信息:正常信 ...

  7. Java常见运算符整理

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/44724267 本文主要介绍Java中常见的运算符,重点介绍 ...

  8. UTF-8是现在流行的编码方式,根据规定回答问题

    UTF-8是现在流行的编码方式,下面是RFC2279对UTF-8编码规则的规定 UCS-4 range (hex.) UTF-8 octet sequence (binary) 0000 0000-0 ...

  9. Android绘图机制(一)——自定义View的基础属性和方法

    Android绘图机制(一)--自定义View的基础属性和方法 自定义View看起来,确实看起来高深莫测,很多Android开发都不是特别在行这一块,这里面的逻辑以及一些绘画都是有一点难的,说一下我目 ...

  10. VMWare安装Ubuntu装完之后安装VMtools

    今天搭建Hadoop环境,在虚拟机中安装了Ubuntu系统,但是Windows系统不能给虚拟机系统传输文件,很是不方便.在网上找了很久,也是过了很多办法,但是下面的方式是可行的,希望对读者有帮助. 第 ...