1、Dubbo源码系列-初识

242 阅读5分钟

大家好,我又来了,距离上次更已经20天了,这段时间,除了忙工作,就是再看Dubbo的相关源码。接下来的一段时间,会逐渐的为大家揭开Dubbo的相关设计,以及各种源码实现,同时也对自己的知识体系做个沉淀。

RPC介绍

RPC,全称Remote Procedure Call,即远程服务调用。一般来说,不同的公司由于技术栈选型以及基础能力的储备,可能会选择不同的解决方案,来作为自己内部服务通信的基石。

业界有名的PRC框架如阿里的Dubbo,FaceBook的Thrift,Google的GRC,还有老东家的moa(手动狗头🐶x1)等等。混迹四家互联网大小厂的笔者有幸在生产环境中用过Thrift、Grpc、以及公司自研的moa框架。以上不同的RPC框架都有各自的优点,如Thrift本身基于IDL定义服务描述,客户端和服务端可以选择用不同的语言实现,能够很好的支持跨语言通信;Grpc底层基于http2,提供了几种不同的通信方式,其中我觉得最有意思的则是双流模式,服务端和客户端可以互相持续通信;至于老东家自研的框架,也是根据公司的技术栈,整合了很多不同的功能,这里就不赘述了。

说到这可能就有作者会提问题了,那么,为什么要单独研究Dubbo,而不是介绍自己用过的其他RPC框架呢?

简介

Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的RPC实现服务的输出和输入功能,作为阿里SOA服务化治理的核心方案,目前已经从Apache孵化器项目毕业。虽然阿里内部已经放弃使用了dubbo(手动狗头🐶x2),但是其优秀的架构设计和扩展能力对于我们平时进行架构设计也是有很多参考意义。再者说了,又有几家的体量能达到阿里的水平呢,可能Dubbo已经不适合阿里了,但是未必就不适合你嘛。目前Dubbo已经更新到3.0版本,不过笔者之前几次看源码基本都是2.x的版本,因此,本系列继续会选择2.x系列作为研究的对象。

整体架构

image.png 万变不离其宗,其实不同RPC的架构都大差不差,整体分为客户端、服务端、注册中心三大部分。

  • 服务端启动的时候,向注册中心注册自己的信息,如服务名称、方法名、ip端口等;
  • 客户端启动的时候,从注册中心拉取自己依赖的服务信息,通过负载均衡算法,选出一台机器进行通信;
  • 客户端和服务端之间可以自定义通信协议如dubbo的dubbo协议,thrift自定义二进制协议等等。支持多种列化协议方式如json、protobuf等;
  • 各个环节都会增加对应的打点监控,进而可以提供较为完善的监控,如服务维度或者接口维度的qps统计,耗时统计等
  • 框架也会提供多种降级策略供业务选择

分层架构

image.png (取自官网)

  • config 配置层:对外配置接口,以 ServiceConfig, ReferenceConfig 为中心,可以直接初始化配置类,也可以通过 spring 解析配置生成配置类
  • proxy 服务代理层:服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton, 以 ServiceProxy 为中心,扩展接口为 ProxyFactory
  • registry 注册中心层:封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 RegistryFactory, Registry, RegistryService
  • cluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster, Directory, Router, LoadBalance
  • monitor 监控层:RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口 为 MonitorFactory, Monitor, MonitorService
  • protocol 远程调用层:封装 RPC 调用,以 Invocation, Result 为中心,扩展接口为 Protocol, Invoker, Exporter
  • exchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer
  • transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec
  • serialize 数据序列化层:可复用的一些工具,扩展接口为 Serialization, ObjectInput, ObjectOutput, ThreadPool`

除了Service层和Config层之外,其他层均为SPI层,这就意味着其他层均可被替换。另外,Dubbo增强了JDK中提供的标准SPI功能,扩展点可以通过setter方法注入其他扩展点,并且,不会一次性实例化扩展点的所有实现类,避免了 资源浪费。

学习难点

  • 基于SPI设计,并非传统意义上的直接new某个对象,因此阅读源码前,一定要优先搞懂SPI到底是什么
  • Filter链,Dubbo很多特性都是基于Fiter链实现,大概提供了20+不同实现,在调用到某个方法前,可能经历过很多个Filter链,因此梳理调用关系的时候一定要搞清楚到底经历过了哪些调用链

参考资料

开胃菜,后续会逐渐的为大家呈上dubbo的SPI设计 && 动态编译原理、客户端调用流程、服务端注册流程、线程模型和线程池策略、集群容错、负载均衡等等,感兴趣的同学可以先收藏(手动狗头🐶x3)