Dubbo 服务暴露与引用原理

Dubbo 服务暴露与引用原理

薛定谔的汪

Dubbo 服务暴露与引用原理

这一块面试最爱问:Dubbo 是怎么把一个接口变成远程服务,又怎么在调用端像调用本地方法一样调用远程的?

核心就两件事:

  1. 服务暴露(Provider 端):把接口方法 → 发布成网络可调用服务
  2. 服务引用(Consumer 端):接口 → 生成代理对象,调用时走远程 RPC

全程围绕:动态代理 + 网络通信 + 注册中心


一、服务暴露(Provider 启动时做什么)

一句话总结

扫描注解 / 配置 → 包装成 Invoker → 启动 Server 监听端口 → 注册到注册中心

1. 扫描与包装

  • 扫描 @DubboService 或 XML 配置的接口实现类

  • 真实实现类 + 方法

    封装成一个

    Invoker

    • Invoker 是 Dubbo 核心模型:可执行对象
    • 可以理解为:能被调用、能执行方法的统一抽象

2. 协议暴露(启动网络服务)

根据配置协议(dubbo/grpc/triple):

  • 启动 Server(Netty 服务器)
  • 监听 IP:Port(默认 20880)
  • 把 Invoker 再包装成 Exporter 持有,用于接收请求

3. 注册到注册中心

  • 将服务信息(接口名、版本、分组、IP、端口、协议、权重)
  • 注册到 Registry(Nacos/ZK)
  • 供消费者发现

一句话:

Provider 把实现类包成 Invoker,启动 Netty 监听,再把地址注册出去。


二、服务引用(Consumer 启动时做什么)

一句话总结

订阅注册中心 → 拿到地址列表 → 生成远程 Invoker → 创建动态代理对象注入 Spring

1. 订阅服务

  • 扫描 @DubboReference 接口
  • 向注册中心订阅该接口
  • 注册中心推送服务地址列表
  • Consumer 本地缓存地址

2. 创建远程 Invoker

根据地址列表,构建一个可以发起远程调用的 Invoker

这个 Invoker 内部会做:

  • 负载均衡
  • 网络通信(Netty Client)
  • 序列化 / 反序列化
  • 集群容错(重试、降级等)

3. 生成动态代理(关键)

给接口生成代理对象,Dubbo 用两种代理:

  • JDK 动态代理(接口代理,默认)
  • Javassist 动态代理(性能更高,常用)

代理对象的核心逻辑:

调用接口方法 → 拦截 → 封装请求 → 远程调用 → 返回结果

4. 注入 Spring

把代理对象放入 Spring 容器

你在业务类 @Autowired 注入的,其实是代理对象


三、一次方法调用完整流程(面试必背)

你在 Consumer 写:

1
userService.getUserById(1L);

真实执行链路:

  1. 调用代理对象方法
  2. 经过一系列 Filter(监控、限流、日志、上下文)
  3. 经过 Cluster 集群层:选择负载均衡策略
  4. 选中一个 Provider 地址
  5. 经过 Directory 目录层:获取可用服务列表
  6. 构建 RPC 请求对象(方法名、参数、版本、 attachments)
  7. 序列化参数
  8. 通过 Netty 长连接发送给 Provider
  9. Provider 端 Netty 接收请求
  10. Provider 经过 Filter 链
  11. 找到对应的 Invoker,反射调用真实实现类方法
  12. 执行结果序列化返回
  13. Consumer 收到结果,返回给业务代码

1. Dubbo 用的是什么代理?为什么不用 Cglib?

  • 默认 JDK 代理,也支持 Javassist
  • Dubbo 都是面向接口的服务,不需要类代理
  • Javassist 比 Cglib 更快、更轻量

2. Invoker 是什么?

Dubbo 的核心模型:

  • Provider Invoker:封装本地实现类

  • Consumer Invoker:封装

    远程调用逻辑

    所有扩展(Filter、路由、负载均衡)都围绕 Invoker 做 AOP。

3. 服务注册是在暴露前还是后?

先暴露端口启动服务,再注册到注册中心。

避免服务还没启动完就被调用,导致报错。

4. 注册中心挂了,服务还能调用吗?

能。

  • Consumer 本地缓存了服务地址列表
  • 调用是点对点直连,不经过注册中心
  • 只是新服务上下线不能实时感知

五、极简总结

  1. 服务暴露:Provider 将实现类包装为 Invoker,启动 Netty Server 并注册到注册中心。
  2. 服务引用:Consumer 订阅地址列表,创建远程 Invoker,并通过动态代理生成接口代理对象。
  3. 调用时通过代理拦截,经过负载均衡、网络通信,最终反射调用 Provider 真实方法。
  4. 整体架构高度 SPI 扩展,所有核心组件均可替换。
  • Title: Dubbo 服务暴露与引用原理
  • Author: 薛定谔的汪
  • Created at : 2022-03-02 19:44:48
  • Updated at : 2026-03-18 15:27:57
  • Link: https://www.zhengyk.cn/2022/03/02/dubbo/dubbo-2/
  • License: This work is licensed under CC BY-NC-SA 4.0.