说说 Dubbo 的实现原理
Dubbo 作为 RPC 框架,实现的效果就是调用远程的方法就像在本地调用一样。如何做到呢?
- 本地有对远程方法的描述,包括方法名、参数、返回值,在 Dubbo 中是远程和本地使用同样的接口
- 要有对网络通信的封装,要对调用方来说通信细节是完全不可见的,网络通信要做的就是将调用方法的属性通过一定的协议(简单来说就是消息格式)传递到服务端
- 服务端按照协议解析出调用的信息;执行相应的方法;在将方法的返回值通过协议传递给客户端;客户端再解析;在调用方式上又可以分为同步调用和异步调用;
三条是 RPC 的通用骨架,Dubbo 的独特之处在于它的微内核+SPI 扩展架构与全链路治理设计。本文按”架构形态 → 调用链对象流 → 注册中心交互 → SPI 机制”四层展开。
架构形态:微内核 + SPI
Dubbo 内核只做流程编排(Protocol/Cluster/Registry 等接口),全部能力以 SPI 扩展点插入:
- 协议:dubbo / triple / rest / grpc
- 注册中心:zookeeper / nacos / consul / 直连
- 序列化:hessian2 / protobuf / kryo / fastjson
- 负载均衡:random / roundrobin / leastactive / consistenthash
- 集群容错:failover / failfast / failsafe / failback / forking
与 JDK SPI(全量实例化)不同,Dubbo SPI 按 key 按需加载(@SPI("dubbo") + ExtensionLoader.getExtension("name")),并支持 IOC 注入与 AOP 包装(扩展点自动包裹 Wrapper)——配置即选型,URL 参数驱动扩展组装是 Dubbo 的设计哲学(”一切皆可 URL”)。
调用链:消费者侧对象流
- 代理:ReferenceBean 为接口生成 JDK 动态代理(InvokerInvocationHandler)
- Invoker 抽象:调用被统一建模为
Invoker.invoke(Invocation)——本地、远程、集群都是一种 Invoker(统一抽象是 Dubbo 设计精髓) - Cluster 层:Directory 列出可用 Invoker(来自注册中心缓存)→ Router 链过滤(条件路由/标签路由)→ LoadBalance 选一个 → 容错策略包裹(failover 重试)
- Protocol 层:DubboProtocol 把 Invocation 编码为 Dubbo 协议帧(magic + 标志位 + requestId + body),经 Netty 长连接发送;多路复用:单连接上按 requestId 匹配响应(DefaultFuture 表)
- 异步转同步:同步调用即 future.get 阻塞等待;异步(CompletableFuture)直接返回 future
调用链:提供者侧对象流
- Netty 收包解码 → Dispatcher 按线程模型(all/固定/缓存等)派发业务线程池
- 按 serviceKey(接口:版本:分组)+ 方法名在 Exporter 表定位实现 bean
- 反射调用(或泛化调用 GenericService 无需接口)→ 结果编码回写(同 requestId)
- 过滤器链包裹全程:限流(tps)、鉴权、trace、监控埋点(Filter 链即 SPI 扩展点)
注册中心交互:通知式服务发现
- 提供者启动:export 时向注册中心注册 URL(ip/port/接口/参数)
- 消费者启动:订阅接口,注册中心推送提供者列表;本地缓存 + 变更通知(非每次调用查询)
- 注册中心宕机:已缓存列表仍可用(可用性设计);新订阅失败
- 心跳与临时节点:提供者宕机由注册中心剔除并通知消费者(ZK 临时节点/ Nacos 健康检查)
协议帧与心跳
Dubbo 协议:16 字节头(magic 0xdabb、请求/响应标志、序列化 id、status、requestId、body 长度)+ body。默认心跳 60s 维持长连接活性、检测死链;超时(默认 1s)由消费者侧 DefaultFuture 定时扫描触发。
与 Spring 的集成面
- @DubboReference/@DubboService(或 XML)声明消费/提供
- ServiceBean/ReferenceBean 作为 FactoryBean 把 Dubbo 生命周期接入 Spring(启动 export、关闭 unexport)
- 配置中心(Nacos/Apollo)动态改路由/限流规则,无需重启
原理主线回顾
统一抽象 Invoker + SPI 微内核 + URL 驱动组装 + 注册中心通知式发现 + 长连接多路复用——五者构成 Dubbo”本地调用体验”的全部支撑。读懂 Invoker 与 SPI 两个设计,Dubbo 源码的其余部分都是这两个思想的重复应用。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 非鱼小站!
评论
WalineDisqus











