Dubbo 还是 Spring Cloud?从架构本质到落地选型

摘要

微服务架构的本质,只分为两大模块:服务创建 + 服务治理 。Spring Boot 解决"如何快速创建应用 ",而 Spring Cloud、Dubbo 是两套截然不同的微服务治理体系 。Spring Cloud 是积木式组件体系,主打 HTTP REST;Dubbo 是一体化 RPC 框架,依托强契约接口做服务定义,内置全套治理能力。企业落地的经典架构思想:对外 REST 求兼容,对内 RPC 求性能;南北走 REST,东西走 RPC。本文从底层原理、流量分层、通信模型,结合企业落地实践,对比两套体系的差异,重点从连接模型、协议设计、序列化、线程模型、调用路径到设计取舍,由表及里六层拆解 RPC 高性能的完整因果链,给出落地选型判断依据。

一、微服务的本质:两件事------服务创建 + 服务治理

服务创建:Spring Boot 作为底座

Spring Boot 核心思想是约定大于配置,自动配置、内嵌容器,大量减少 XML、繁杂 Bean 配置,让开发者快速搭建出独立可运行的 Java 应用。

当应用数量变多,几十个、上百个服务部署运行之后,就会产生新的诉求:服务在哪、能不能调用、负载怎么分配、调用失败如何处理、流量灰度怎么控制。这部分就是服务治理。

服务治理有两套主流落地体系:Spring Cloud 和 Dubbo。

对比项 Spring Cloud Dubbo
定位 积木式组件拼装,按需引入 一体化 RPC 框架,原生内置全套治理
服务形态 HTTP REST(面向资源 URL) 强契约接口模型(面向接口方法)
通信模型 HTTP,每次请求响应语义独立,无单连接多路复用 TCP 长连接,多路复用
序列化方案 JSON 文本 二进制(Hessian2/Protobuf),插件化可替换
治理能力 按需选配注册中心、负载均衡、限流组件 注册发现、负载均衡、集群容错、路由全部开箱即用
分组与版本 无原生分组能力,依靠 metadata 自定义扩展实现 原生内置 Group / Version,直接用于服务分组、版本隔离
契约强弱 弱契约,依靠接口文档维护,消费端不需要共享代码 Jar 包 强契约,消费方必须引入接口 Jar 包,接口作为通信契约
跨语言 HTTP 协议天然跨语言,任意语言均可接入 以 Java 生态优先,跨语言体验偏弱
调试手段 HTTP 可直接使用 curl、Postman 调试,简单方便 私有 RPC 协议,无法直接 curl 调试,依赖 Dubbo 专用管理工具

Dubbo 同样构建在 Spring Boot 之上,但它改变了服务对外暴露的形态。

Spring Cloud 生态里,服务是以 HTTP 的 GET/POST 接口对外提供;而 Dubbo 不是 HTTP 接口,它采用**IDL 接口定义语言**,在服务提供者与消费者之间提前约定接口、方法、入参、返回值,形成双方都必须遵守的强契约。

  • 服务提供者 :使用 @DubboService 注解,将接口实现类发布为 RPC 服务;
  • 服务消费者 :使用 @DubboReference 注入远程服务代理,调用远程接口就像调用本地普通 Java 方法。

二、RPC 高性能的本质

在内网服务调用场景,Dubbo、gRPC 这类 RPC 框架,相比 Spring Cloud Feign 的 HTTP 调用,拥有更低的延迟、更高的吞吐。

RPC 高性能的本质,不是某一项技术优势,而是一整套"为内网 Java 调用量身定制"的设计取舍:放弃跨语言通用性,换取紧凑协议与二进制序列化;绕过 Servlet 容器,缩短调用路径;复用 TCP 连接,减少握手开销。每一层都在做减法,减到最后就是性能。

这套分层优化体系覆盖网络连接、协议编码、对象序列化等全链路。本节由底层向上逐层拆解 RPC 高性能的全链路因果逻辑。

2.1 连接模型(TCP 长连接 + 多路复用)

Spring Cloud REST 基于 HTTP 协议(常用 HTTP/1.1),每次请求-响应语义独立,无法在单连接上并发复用多个请求;相比 Dubbo 的 TCP 多路复用,仍存在连接建立的开销。

HTTP/1.1 虽然支持 Keep-Alive 保持长连接,但一条连接同一时刻只能串行处理一组请求响应。高并发场景下,需要创建大量连接,带来 TCP 握手、操作系统连接队列、文件句柄等额外开销。

Dubbo 底层直接基于TCP 长连接 ,一次握手建立连接之后可以长期复用。并且 Dubbo 实现了连接多路复用:一条 TCP 连接上,可以并发传输多个 RPC 请求,请求和响应依靠请求 ID 一一对应,不需要为每一次方法调用新建一条 TCP 连接。

性能收益:

  1. 省去反复创建、销毁 TCP 连接带来的三次握手/四次挥手开销;
  2. 单连接承载大量并发请求,大幅减少操作系统文件句柄、连接资源占用。

2.2 协议设计(自定义紧凑二进制协议)

HTTP 属于文本协议,报文自带大量冗余 Header:Cookie、Accept、User-Agent 等文本头,每次请求重复携带,报文体积大,包含大量换行、空格、分隔符这类非业务冗余字符。

Dubbo 使用自研紧凑二进制协议,协议头极简,只保留核心字段:请求 ID、版本号、序列化类型、消息长度等,没有 HTTP 协议的文本冗余。

性能收益:

  1. 报文头部体积极小,减少网络传输的数据量;
  2. 二进制帧结构便于机器解析,不需要文本词法分割,降低编解码开销。

2.3 序列化(二进制编码)

Spring Cloud REST 默认使用 JSON 序列化,属于纯文本格式。JSON 会把所有数据全部转为字符串存储:数字、布尔、对象全部变成文本字符,依靠引号、逗号、大括号、冒号做结构分割。

例如数字 123,在 JSON 中是以字符串 "123" 存储,而非原生二进制数字,存在空间浪费与解析开销。

JSON 文本序列化三大短板:

  1. 报文体积大:大量分隔符、引号、键名重复传输,网络流量开销高;
  2. CPU 开销高:每次调用需要完整词法解析、字符串拆分、类型转换,解析耗时严重;
  3. 类型不安全:文本丢失原生类型信息,反序列化需要大量类型推断、兼容处理,容易出现类型异常。

Dubbo 支持二进制序列化 (默认 Hessian2,同时支持 Protobuf、Kryo 等),并且序列化与通信协议完全解耦,可插件化切换。

二进制序列化直接将 Java 对象按照二进制字节码写入网络流,不需要转文本、不需要分隔符,数字、布尔、对象类型直接以原生二进制存储。

二进制序列化性能收益:

  1. 序列化后字节体积极小,大幅降低网络传输耗时与流量开销;
  2. 无需文本词法解析,直接二进制编解码,CPU 消耗极低,序列化/反序列化速度远快于 JSON;
  3. 天然保留强类型信息,配合 Dubbo 接口强契约,类型校验精准、无转换异常。

2.4 线程模型层:IO 线程与业务线程池隔离

Dubbo 底层通信基于 Netty,采用标准 Reactor 线程模型,IO 线程和业务线程池做了彻底隔离。

IO 线程(EventLoop)只负责网络字节的读写、编解码,不执行业务逻辑,保证 IO 线程不会被阻塞;反序列化完成后,请求会投递到独立业务线程池执行业务代码。

对比传统 Servlet 模型(Tomcat):采用一请求一线程模型,一个请求绑定一条独立线程。如果业务代码发生 DB、Redis 这类阻塞 IO,线程会被卡住,无法处理其他请求,高并发下容易耗尽线程资源。

即便使用 WebFlux 异步非阻塞,HTTP 请求从进入容器到返回响应,依然要走完完整 Filter 链、DispatcherServlet 调度,存在固定调度开销。

Dubbo 这套线程隔离设计,保证网络 IO 不会被业务阻塞,高并发场景下线程切换开销更低,资源利用率更高。

Dubbo 默认配置:Boss 线程数 = 1,Worker(IO)线程数 = CPU 核数 × 2,业务线程池默认 200 个线程(可通过 threads 参数调整)。三层线程各司其职,互不阻塞。

2.5 调用路径层:接口代理,精简调用链路

Spring Cloud Feign 的一次完整调用链路:

Feign 代理 → HTTP 客户端 → 建立/复用连接 → 组装 HTTP 报文 → JSON 序列化 → 网络传输 → Tomcat 接收 → HTTP 解码 → DispatcherServlet 路由 → Controller 参数解析 → 调用 Service

Dubbo 的一次 RPC 调用链路:

DubboReference 代理 → 负载均衡选实例 → Netty 发送二进制帧 → 网络传输 → Netty IO 线程读取帧 → 反序列化 → 直接调用接口实现方法

Dubbo 基于接口代理做远程调用,直接绕过 Servlet 容器、Filter 拦截器链、HTTP URL 路由、Controller 参数绑定整套 HTTP 生命周期,调用链路大幅缩短,减少了大量中间调度开销。

2.6 设计取舍层:放弃通用性,换取内网调用极致性能

这是 RPC 高性能最根本的原因。

HTTP REST 从设计之初就要兼容浏览器、移动端、多语言客户端,通用性是第一目标,为了通用不得不承担额外开销,也就是通用性性能税。

而 Dubbo 这类 RPC 框架,设计目标非常聚焦:服务内网 Java 服务之间高频调用。

基于这个前提,它主动做了一系列取舍:

  • 不需要兼容浏览器,不必遵守 HTTP 全套语义;
  • 不优先跨语言,可使用 Java 友好的二进制序列化;
  • 报文不需要人类可读,协议头可以做到极简紧凑;
  • 不需要通用容器,可绕过 Servlet,直接做接口方法调用。

所有的性能优化,都建立在这一场景取舍之上。不是单纯技术更强,而是场景更专一。

2.7 综合性能总结

HTTP + JSON(Spring Cloud):文本协议、单连接无法多路复用、报文头部冗余严重、文本解析 CPU 开销大。核心优势是通用、跨语言、可调试,为了兼容浏览器、多语言、各类中间件,牺牲了性能,自带「通用性性能税」,天生不适合内网高频调用。

TCP + 二进制 RPC(Dubbo):长连接复用、单连接多路并发、极简二进制协议头、高效二进制编解码,全方位减少网络 IO 与 CPU 开销,在内网高频服务调用场景,实现低延迟、高吞吐。

终极架构结论:

HTTP 是「为通用兼容而生」,RPC 是「为内网性能而生」。对外 REST 求兼容,对内 RPC 求性能,不是技术选型的偏好,是架构设计取舍的必然结果。表层的协议、序列化差异,只是底层整套架构设计优势的最终体现。

RPC 高性能的完整因果链(由表及里)

层次 做了什么 性能收益
① 序列化层 二进制替代文本 JSON 体积更小、CPU 解析更快
② 协议层 自定义紧凑二进制协议替代 HTTP 文本协议 去掉冗余 Header,报文头部极简
③ 连接层 TCP 长连接 + 多路复用替代 HTTP 短连接/独立连接 省去反复握手开销,单连接并发承载
④ 线程模型层 IO 线程与业务线程池隔离(Netty Reactor 模型) 避免阻塞 IO 线程,高并发下线程切换少
⑤ 调用模型层 接口代理 + 方法级调用,无需完整 HTTP 请求生命周期 跳过 Servlet 容器 Filter 链、HTTP 编解码全流程
⑥ 设计取舍层 放弃通用性(跨语言、浏览器兼容),换取极致性能 所有优化都源于"只服务内网 Java 调用"这个前提

三、服务调用容错策略:Dubbo VS Spring Cloud

3.1 Dubbo 消费端集群容错策略

Dubbo 的容错逻辑内置在框架消费端,负载均衡选中实例、发起网络调用失败后,执行对应的集群容错策略,一共 6 种:

  1. Failfast(快速失败):调用一次失败,直接抛出异常,不重试。适合写接口、事务接口,不能重复提交。
  2. Failsafe(失败安全):捕获并吞没异常,不向上抛出,直接返回空。适合埋点、日志上报这类非核心逻辑,允许丢数据,不能影响主业务。
  3. Failback(失败自动恢复):调用失败,立刻给客户端返回成功,不阻塞业务;后台线程异步排队重试。适合消息通知、事件推送,允许延迟送达。
  4. Failover(故障转移,Dubbo 默认策略) :当前节点调用失败,不重试当前节点,自动切换集群内其他可用实例重试 。适合查询读接口;️ 必须保证接口幂等,写接口严禁使用,会产生重复写。
  5. Forking(并行调用):并行同时请求多个实例,任意一个成功就返回结果,适合对延迟极其敏感的查询场景。
  6. Broadcast(广播调用):广播调用所有服务实例,任意一个调用失败,整体判定失败,多用于批量配置更新。

Dubbo 执行链路: Consumer Filter 链 → Cluster 集群容错 → LoadBalance 负载均衡 → 选定实例 → Netty 发起 RPC 网络调用

3.2 Spring Cloud 容错策略(Sentinel / Resilience4j)

Spring Cloud 本身没有内置容错组件,属于按需引入,主流使用 Resilience4j 或者 Sentinel 实现容错,核心能力包含重试、熔断、降级、舱壁:

  1. 重试(Retry) :调用失败自动重试,可以配置重试次数、间隔、异常类型。和 Dubbo Failover 类似,但基于 HTTP 调用,重试会重新走完整 HTTP 请求流程。读接口使用,写接口必须谨慎防止重复提交。
  2. 熔断(CircuitBreaker):当下游失败率超过阈值,打开熔断器,直接快速返回兜底结果,不再发起远程调用,保护下游服务雪崩。
  3. 降级(Fallback):调用异常、超时、熔断触发时,执行预先定义的兜底方法,返回预设结果。可以返回默认值、缓存数据。
  4. 超时(TimeLimiter):限制远程 HTTP 调用最大等待时长,超时直接终止请求,避免线程长时间阻塞。
  5. 舱壁(Bulkhead):隔离线程池,为不同服务调用分配独立线程资源,单个下游故障不会耗尽整个应用线程池,防止服务雪崩。

Spring Cloud 调用链路: Feign 拦截器 → Resilience4j/Sentinel 容错组件 → 负载均衡 → HTTP 请求调用远端服务

3.3 两者容错的核心差异

  1. 内置形态:Dubbo 集群容错原生内置框架;Spring Cloud 容错能力需要额外引入 Resilience4j/Sentinel 组件,按需装配。
  2. 生效位置:Dubbo 容错是 RPC 集群层,在实例选择环节做节点切换;Spring Cloud 容错作用在 HTTP 客户端(Feign)之上。
  3. 熔断能力:Dubbo 3.x 已提供 CircuitBreaker 扩展支持,但生态成熟度和开箱体验不如 Spring Cloud + Sentinel 组合;Spring Cloud 生态天然将熔断降级作为核心容错能力,是应对雪崩的首选方案。
  4. 模型侧重点 :Dubbo 集群容错更多解决实例调用失败后的路由重试 ;Spring Cloud 生态容错重点在于防止服务雪崩、流量降级保护。

四、流量分层最佳实践:南北 REST,东西 RPC

大规模微服务落地,最经典的架构分层就是区分南北流量 与东西流量 ,也就是南北 REST、东西 RPC,两套协议各司其职,不要混用。

对比项 南北流量(外部 内部) 东西流量(内部 内部)
协议 REST / HTTP + JSON TCP/RPC + 二进制序列化(Dubbo/gRPC)
完整链路 客户端 → Nginx 流量网关 → API Gateway 业务网关 → 后端微服务 消费端直连提供端,不经过网关转发
核心目标 兼容性、安全性、可调试 高性能、低延迟、强治理能力
网关分工 流量网关(Nginx):SSL、WAF、全局限流;业务网关(Spring Cloud Gateway):流量染色、Header 标签透传、灰度路由、鉴权 路由、负载均衡、实例过滤、灰度逻辑,在消费端本地执行
标签透传 HTTP Header 透传,网关入口统一打标 Dubbo Attachment 透传,可利用 Group/Version 实现服务分组隔离

南北流量:外部客户端(浏览器、APP、第三方系统)访问内部业务,是系统出入口。外部客户端只认识 HTTP 协议,所以统一使用 REST + JSON。依靠网关统一做安全防护、鉴权、流量管控,同时 HTTP 支持 curl、Postman,接口调试便捷,优先保证兼容性与安全性。

东西流量:微服务和微服务之间的内部调用,属于内网闭环通信,没有跨语言强制要求。选用 Dubbo 这类 RPC 框架,基于 TCP 长连接 + 二进制序列化,服务之间点对点直连,省去网关转发损耗,追求高吞吐、低延迟,同时依托框架内置能力做服务治理。

五、选型怎么选?落地判断标准

优先 Spring Cloud(HTTP REST)

  1. 对外网关接入,承接南北流量,面向浏览器、App、第三方系统对接;
  2. 多语言混合技术栈,需要跨语言调用;
  3. 团队技术栈熟悉 HTTP,业务以简单 CRUD 为主,没有极高吞吐、低延迟诉求;
  4. 希望组件解耦,可自由替换注册中心、网关等组件,快速调试接口。

优先 Dubbo(RPC)

  1. 服务集群内部大量东西向高频服务调用,追求高性能、低延迟;
  2. 需要原生的服务分组、版本隔离,做灰度、版本管控;
  3. 团队希望框架自带完整治理能力,不想自己组装一堆中间件;
  4. 强契约约束,接口版本管理严格,适合金融、企业级核心 Java 业务。

现实生产最佳架构 :二者可以完美共存,也就是对外 REST + 对内 RPC 架构。网关用 Spring Cloud Gateway 承接外部 HTTP 请求,服务内部互调用 Dubbo RPC,做到:南北流量求兼容、东西流量求性能。

六、全文总结金句

Spring Boot 负责造应用,Spring Cloud 负责拼装治理 HTTP 服务,Dubbo 负责用强契约 RPC 定义服务------全套治理能力原生内置,通信与序列化插件化。

流量网关看门,业务网关调度;对外 REST 求兼容,对内 RPC 求性能;南北走 REST,东西走 RPC。

相关推荐
独孤九剑打醒他1 小时前
【原创开源·航空篇】太阳能水闭环氢能航空:双燃料掺氢助燃与露天储氢安全模型
架构·开源·汽车·硬件工程·能源
晴殇i2 小时前
双模式、多 Agent、三端接力:我用 TRAE 把「YACA」从需求推到了交付
架构
海宇大数据2 小时前
零信任架构实战:基于海宇企业综合风险报告构建自动化供应链保理对公尽调网关
运维·人工智能·架构·自动化
诚心呈意共享外卖配送系统2 小时前
多平台订单聚合系统的技术架构:接 API 只是开始
java·开发语言·架构·系统架构·创业创新
省钱兄--zs2 小时前
碰碰好评卡系统开发实战指南 核心功能实现与部署落地全流程拆解
数据仓库·经验分享·spring boot·小程序·架构
Wang's Blog3 小时前
Java 项目实战: 交友项目 - 前后端分离的工程实践
java·spring cloud·架构
代码方舟3 小时前
零信任架构实战:基于天远普通维保查询构建自动化二手车融资租赁资产入库审计网关
人工智能·架构·自动化
2603_954708313 小时前
如何进一步优化微能网协调控制箱的架构优势
大数据·数据库·人工智能·分布式·架构