1.5 java面试题:Dubbo
Dubbo 作为国内 Java 微服务生态中最核心的 RPC 框架,面试考察点已经从简单的“怎么用”全面转向了“原理、协议、容错、SPI 扩展以及与 Spring Cloud 的对比选型”。结合你的银行核心背景和之前的知识点,我梳理了 10 个高频 Dubbo 面试题,从架构原理到生产落地逐一讲透。
1. 什么是 Dubbo?它在微服务架构中扮演什么角色?
答:
Dubbo 是阿里巴巴开源的一款高性能 Java RPC 框架,核心解决分布式系统中服务间的透明化远程调用。它不仅仅是通讯框架,更是一套完整的服务治理方案,涵盖了:
- 服务注册与发现(Registry)
- 远程调用(RPC)
- 负载均衡
- 集群容错
- 服务路由与降级
在银行微服务中,我们把核心交易线(如存取款、转账)下沉到 Dubbo,利用其毫秒级延迟和高吞吐特性,对外 API 网关才用 HTTP。
2. Dubbo 的核心调用流程是怎样的?
答:
Dubbo 一次调用涉及Provider、Consumer、Registry、Monitor四个角色:
- Provider 启动时,向注册中心(如 Zookeeper/Nacos)注册自己提供的服务接口。
- Consumer 启动时,向注册中心订阅所需的服务,拉取 Provider 地址列表并缓存本地。
- Consumer 通过动态代理调用接口,内部将方法名、参数序列化,通过 Netty 发送给 Provider。
- Provider 反序列化请求,执行本地实现,将结果序列化返回。
- 监控中心(Monitor)统计调用次数、耗时等。
银行案例:存款服务(Consumer)调贷款服务(Provider)查询额度,走的就是这个流程。
3. Dubbo 的负载均衡策略有哪些?默认是什么?
答:
Dubbo 提供 4 种内置负载均衡策略,可在@DubboReference(loadbalance="xxx")配置:
- Random(默认,加权随机):按权重随机,概率均匀,适合实例性能相近。
- RoundRobin(加权轮询):平滑加权轮询,避免突刺,适合同规格实例。
- LeastActive(最小活跃数):选当前处理请求最少的实例,避免慢节点堆积,适合耗时差异大的场景(如调征信)。
- ConsistentHash(一致性哈希):相同参数(如账号ID)总发同一实例,适合有状态缓存(如客户信息缓存)。
银行实践:核心查询用加权轮询,耗时接口用最小活跃数,灰度发布时自定义基于元数据的路由。
4. Dubbo 的集群容错模式有哪些?默认是什么?
答:
Dubbo 提供了 6 种容错策略:
- Failfast(默认):快速失败,立即报错,用于非幂等写操作。
- Failsafe:忽略异常,记录日志,用于旁路通知。
- Failback:失败后异步重试,用于最终一致性的操作。
- Forking:并行调用多个实例,取最先返回的结果,用于低延迟要求但耗资源。
- Broadcast:广播调用所有实例,逐台确认,用于缓存更新通知。
- Failover:失败自动切换,重试其他实例(通常用于读操作)。
银行实践:对于资金转账这类关键写操作,我们使用Failfast,禁止重试,防止重复扣款;对于非关键查询,使用Failover并限制重试次数。
5. Dubbo 支持的协议有哪些?如何选择?
答:
Dubbo 支持多种协议,最常用:
- dubbo 协议(默认):单一长连接 + NIO 异步通讯,基于 Netty。适合小数据量高并发的服务间调用,但传输大文件慢。
- hessian:基于 HTTP 的二进制协议,适合跨语言。
- rest:标准 HTTP + JSON,适合对外开放。
- grpc:基于 HTTP/2,适合流式或跨语言高性能场景。
银行实践:核心交易线用dubbo://协议压榨性能;对接外部系统可能用rest://或grpc://。
6. Dubbo 的服务治理能力体现在哪些方面?
答:
除了负载均衡和容错,Dubbo 还提供了:
- 动态路由:通过控制台实时调整路由规则,如灰度发布、读写分离。
- 权重动态调整:不停机上下线,双十一期间可临时为某批实例降权。
- 服务降级:
mock机制,在服务不可用时强制返回 mock 数据。 - 参数回调:Consumer 向 Provider 注册回调,实现异步通知。
- 本地存根:在消费端执行预处理或校验。
银行实践:我们通过配置中心下发路由规则,将黑名单用户的流量切到专用实例,实现业务隔离。
7. Dubbo 的 SPI 机制是什么?为什么很重要?
答:
Dubbo 的扩展点几乎全部通过微内核 + SPI实现。Java 原生 SPI 会一次性实例化所有扩展,而 Dubbo 改进了 SPI,支持:
- 按需加载:只有用到的扩展才实例化。
- IOC/AOP:扩展点可以注入其他扩展,支持包装类增强。
- 自适应扩展:
@Adaptive注解动态选择实现(如根据 URL 参数选协议)。
示例:Protocol接口是 SPI 扩展点,dubbo、hessian、rest是不同实现,运行时根据 URL 的前缀自动选中。
8. Dubbo 和 Spring Cloud 全家桶如何对比选型?
答:
- Dubbo:定位为高性能 RPC 框架,强于服务治理,自定义二进制协议,延迟低、吞吐高。适合纯 Java 内部服务间调用。
- Spring Cloud:定位为微服务一站式解决方案,生态完整(网关、配置中心、熔断、链路追踪等)。基于 HTTP 协议,普适性好,但性能低于 Dubbo。
- 选型决策:
- 需要极致性能且同构 Java 服务 → Dubbo。
- 需要多语言、或者要整体解决方案 → Spring Cloud。
- 银行实践:内部核心交易走 Dubbo,外部 OpenAPI 走 Spring Cloud Gateway。
9. Dubbo 服务的发布与引用有几种方式?
答:
- XML 配置:传统 Spring 项目使用
dubbo:service和dubbo:reference标签。 - 注解:
@DubboService暴露服务,@DubboReference引用服务(常用)。 - API 方式:手动构建
ServiceConfig和ReferenceConfig(不依赖 Spring)。
现代项目基本都用注解方式,简洁且与 Spring Boot 深度集成。
10. Dubbo 服务暴露的延迟与优雅上下线如何处理?
答:
- 延迟暴露:
delay="-1"或delay="5000",在 Spring 容器初始化完成后再暴露服务,避免启动期间被调用而失败。 - 优雅下线:
- 服务提供者:先调用
ServiceBean#unexport()从注册中心撤销,然后等待已进入请求处理完毕。 - 结合 Dubbo 3.x 的“应用级服务发现”,可做到秒级摘除。
- 容器环境(K8s)配合
preStop钩子,先通知 Dubbo 摘除,再等待流量排干。
- 服务提供者:先调用
- 银行实践:我们通过自定义 HealthCheck 接口,与 Dubbo 摘除联动,确保发版时交易损失为零。
面试模板话术
“Dubbo 方面我主要从 RPC 调用、负载均衡、容错机制和 SPI 扩展这几个维度掌握。
一次完整调用是 Provider 注册、Consumer 发现、代理发起 Netty 通讯。负载均衡默认加权随机,我们银行核心根据接口特性灵活选用最小活跃或一致性哈希。容错上资金类写操作用 Failfast 防止重复扣款,查询类用 Failover 切换。
关于协议,内部全用 dubbo 协议长连接,外部才用 HTTP。服务治理上,我们通过控制台动态调权、灰度发布,并自研健康检查工具联动 Dubbo 摘除,做到优雅上下线。
Dubbo 就像我们内部 RPC 的核心骨骼,保障了毫秒级的交易体验。”
