APISIX + Nacos + Dubbo 整合实践:以订单服务为例
在 Dubbo 微服务体系中,外部客户端通常使用 HTTP/HTTPS,而内部服务使用 Dubbo RPC,Nacos 负责注册与服务发现。传统方案往往需要额外部署 HTTP Adapter,将 HTTP 请求转换为 Dubbo 调用。本文以订单查询与下单业务为例,整理 APISIX、Nacos 与 Dubbo 的整合方式,重点说明服务发现、HTTP→Dubbo 协议转换、Dubbo 3 注册模型、动态扩缩容、版本兼容以及生产环境容易踩到的问题。
为什么需要 APISIX + Nacos + Dubbo
假设一个典型的订单系统已经采用 Dubbo 构建内部微服务:
1 | |
内部调用可能是:
1 | |
但浏览器、App、小程序或者第三方系统不可能直接调用 Dubbo,它们通常使用:
1 | |
于是南北向流量会遇到两个问题:
- HTTP 与 Dubbo 的协议不同,需要协议转换。
- Dubbo Provider 地址动态变化,网关不能把 Provider IP 写死。
传统做法通常是在 Dubbo 服务前面再增加一个 HTTP Adapter:
flowchart LR
Client[Web / App / 第三方系统]
Gateway[API Gateway]
Adapter[Order HTTP Adapter]
Nacos[Nacos]
Order1[Order Dubbo Provider #1]
Order2[Order Dubbo Provider #2]
Client -->|HTTP| Gateway
Gateway -->|HTTP| Adapter
Adapter -->|Dubbo| Order1
Adapter -->|Dubbo| Order2
Adapter -. 服务发现 .-> Nacos
Order1 -. 注册 .-> Nacos
Order2 -. 注册 .-> Nacos
这种架构当然能工作,而且当 Adapter 承担 API 聚合、DTO 转换、权限模型转换、领域防腐等职责时,它本身也是有价值的。
但如果 Adapter 只是机械地做:
1 | |
那么它会额外增加一次网络跳转、一套部署单元以及一层故障点。
APISIX 与 Dubbo、Nacos 组合的核心思路,就是让 APISIX 同时承担:
1 | |
从而形成:
flowchart LR
Client[Web / App / 第三方系统]
APISIX[Apache APISIX]
Nacos[Nacos Registry]
Order1[order-service #1<br/>Dubbo :20880]
Order2[order-service #2<br/>Dubbo :20881]
Client -->|HTTP / HTTPS| APISIX
Order1 -. 注册 Provider .-> Nacos
Order2 -. 注册 Provider .-> Nacos
APISIX -. 查询并刷新实例列表 .-> Nacos
APISIX -->|Dubbo RPC| Order1
APISIX -->|Dubbo RPC| Order2
这正是早期 APISIX + Dubbo + Nacos 实践要解决的问题:APISIX 一侧处理 HTTP/Dubbo 协议转换,同时通过 Nacos 动态获取 Dubbo Provider,而不是额外维护一层 HTTP Adapter。
需要特别区分两个概念:
Nacos 服务发现解决的是“调用谁”,HTTP→Dubbo 插件解决的是“怎么调用”。
仅仅让 APISIX 从 Nacos 找到 Dubbo Provider,并不代表 APISIX 自动具备 Dubbo RPC 调用能力。
三个组件分别负责什么
在开始配置之前,可以先把职责边界理清。
| 组件 | 核心职责 | 在订单场景中的作用 |
|---|---|---|
| APISIX | API Gateway、路由、鉴权、限流、负载均衡、协议转换 | 接收 /api/orders/** HTTP 请求 |
| Nacos | 服务注册、服务发现、实例管理 | 保存 order-service Provider 地址 |
| Dubbo | RPC 框架 | APISIX 或其他微服务调用订单 RPC |
Nacos 本身并不承载订单请求。
真实业务数据流是:
1 | |
Nacos 更接近控制面:
1 | |
Nacos 官方关于 APISIX 服务发现的实践也是这个模型:服务实例注册到 Nacos,APISIX 根据 Nacos 返回的实例列表动态构建 Upstream。
本文的订单业务场景
假设系统存在一个订单查询 RPC:
1 | |
请求对象:
1 | |
返回对象:
1 | |
内部 Dubbo RPC 是:
1 | |
对外则希望暴露:
1 | |
请求:
1 | |
因此 APISIX 需要完成:
1 | |
这里刻意采用单 Request DTO 参数,而不是:
1 | |
后面会看到,这种接口设计对于 HTTP→Dubbo 协议转换非常重要。
整体调用链
一次订单查询可以抽象成下面的流程。
sequenceDiagram
participant O as order-service
participant N as Nacos
participant C as Client
participant A as APISIX
O->>N: 注册 OrderQueryService Provider
A->>N: 周期刷新 Provider 实例
N-->>A: IP + Dubbo Port
C->>A: POST /api/orders/query
A->>A: Route 匹配
A->>A: 选择 Upstream
A->>A: HTTP → Dubbo 编码
A->>O: queryOrder(request)
O-->>A: OrderView
A-->>C: HTTP Response
注意请求阶段并不是:
1 | |
而是:
1 | |
APISIX 的 Nacos Discovery 模块按照配置周期刷新服务实例,因此不需要每次业务请求都实时查询 Nacos。当前 APISIX Nacos Discovery 配置提供 fetch_interval、连接超时、读取超时等参数。
环境与版本选择
早期 Nacos 官方案例使用的是 APISIX 2.x,2023 年 APISIX + Dubbo + Nacos 示例同样属于较早的 APISIX/Dubbo 组合。今天直接照搬旧配置,最容易遇到的并不是 Nacos,而是 Dubbo 3 注册模型和 Dubbo 序列化方式已经发生变化。
当前 APISIX 文档已经进入 3.x 系列,Nacos Service Discovery、dubbo-proxy 和 http-dubbo 仍然存在。
本文建议把版本兼容拆成两层考虑:
1 | |
APISIX 与 Nacos 的服务发现通常比较直接。
真正需要重点验证的是:
1 | |
官方 Dubbo 3.3 Nacos 注册中心文档给出的示例组合中,Dubbo 3.3.0 对应推荐 Nacos 2.3.0,并兼容 Nacos 2.x。
生产环境不要简单理解为:
APISIX 3.x + Dubbo 3.x + Nacos 3.x,数字越大就一定越兼容。
协议转换层必须单独做兼容性测试。
第一步:创建 Dubbo Order Provider
Maven 依赖
以 Dubbo 3.3.x 为例:
1 | |
这是当前 Dubbo Nacos 注册中心文档提供的 Spring Boot 依赖方式。
Provider 实现
1 | |
一个非常重要的 Dubbo 3 配置:register-mode
配置:
1 | |
这里为什么显式写:
1 | |
而不是使用 Dubbo 3 新项目经常推荐的:
1 | |
这是整个 APISIX + Dubbo 3 整合里最容易忽略的问题。
Dubbo 3 的服务注册模型发生了什么变化
Dubbo 2 时代主要采用接口级服务发现。
例如:
1 | |
在 Nacos 中会形成类似:
1 | |
这个名字包含:
1 | |
完整规则可以理解为:
1 | |
如果没有 Dubbo Group:
1 | |
Dubbo 官方排障资料也明确给出了这种接口级 Nacos Service Name 格式。
但 Dubbo 3 引入了应用级服务发现:
1 | |
服务发现的中心开始从:
1 | |
逐渐转向:
1 | |
Dubbo 3 提供:
1 | |
其中:
| 模式 | 含义 |
|---|---|
interface |
只进行接口级注册 |
instance |
只进行应用级注册 |
all |
两种方式都注册 |
对于新的 Dubbo 3 Consumer,官方更推荐逐步转向应用级服务发现;但 APISIX 并不是一个完整的 Dubbo 3 Consumer,它通常没有 Dubbo MetadataService、应用映射等完整服务发现过程。
而 APISIX + Nacos 的传统整合方法依赖的恰恰是:
1 | |
所以本文显式使用:
1 | |
目的不是说 all 永远是 Dubbo 3 的最佳配置,而是:
为 APISIX 保留接口级 Nacos 注册信息,同时让 Dubbo 3 内部 Consumer 仍然能够使用应用级服务发现。
这是一种兼容策略。
验证订单 Dubbo Provider 是否已经注册
启动:
1 | |
然后可以直接查询 Nacos Open API:
1 | |
如果注册正常,应能够看到类似实例信息:
1 | |
这里真正重要的不是 JSON 长什么样,而是确认三个字段:
1 | |
其中端口必须是:
1 | |
这样的 Dubbo 协议端口,而不是 Spring Boot 的:
1 | |
第二步:让 APISIX 接入 Nacos
APISIX 的 Nacos Service Discovery 需要在 conf/config.yaml 中配置。
当前 APISIX 文档采用类似下面的配置:
1 | |
最简单的配置实际上只需要:
1 | |
不过生产环境建议显式配置超时。
fetch_interval
例如:
1 | |
表示 APISIX 周期刷新 Nacos 服务信息。
开发环境如果希望快速观察实例上下线,可以适当缩短:
1 | |
但刷新频率越高,对注册中心的查询也越频繁。
没有必要为了追求“秒级感知”直接写:
1 | |
特别是网关节点很多时:
1 | |
会无意义地增加 Nacos 压力。
第三步:让 APISIX 根据 Nacos 创建动态 Upstream
普通 APISIX Upstream 可能这样配置:
1 | |
问题是 Provider 扩缩容后必须修改 APISIX。
接入 Nacos 后,则变成:
1 | |
这里不再配置:
1 | |
APISIX 根据:
1 | |
动态查询 Provider。
这正是 Nacos 官方 APISIX 服务发现示例采用的方式。
到这里还不能调用 Dubbo
现在 APISIX 已经知道:
1 | |
但客户端发送的仍然是:
1 | |
而:
1 | |
监听的是 Dubbo RPC Protocol。
所以:
1 | |
不能直接扔给:
1 | |
还必须加入:
1 | |
协议转换。
APISIX 当前仍提供与 Dubbo 相关的 dubbo-proxy 和 http-dubbo 插件。
dubbo-proxy 与 http-dubbo 应该怎么选
当前主要可以看到两种路径。
| 插件 | 特点 | 更适合 |
|---|---|---|
dubbo-proxy |
较早的 APISIX Dubbo 方案 | 兼容已有 APISIX/Dubbo 部署 |
http-dubbo |
APISIX 自己构造 Dubbo 请求 | 需要显式映射 Dubbo 方法签名 |
早期 APISIX + Nacos + Dubbo Demo 使用的是:
1 | |
并且组合了:
1 | |
这是原始实践已经验证过的整合结构。
不过当前 dubbo-proxy 官方文档明确提醒:如果基于 OpenResty,需要使用包含 Dubbo 支持的构建。
http-dubbo 则直接在 APISIX Lua 插件中构造 Dubbo Protocol 数据,并连接 APISIX 已经选择好的 Upstream 节点。当前插件源码可以看到,它最终读取:
1 | |
建立 TCP 连接。由此可以把:
1 | |
组合起来。这里属于根据当前插件实现得出的工程性判断,因此部署前必须针对所使用的 APISIX/Dubbo 版本进行真实冒烟验证,而不能只检查配置是否能保存。
下面以 http-dubbo 说明完整调用过程。
第四步:创建订单查询 Route
假设:
1 | |
对应 JVM Method Descriptor 中的参数描述为:
1 | |
创建 APISIX Route:
1 | |
这里实际上同时完成了两件事情。
Upstream 负责找 Provider
1 | |
解决:
1 | |
http-dubbo 负责调用接口
1 | |
解决:
1 | |
把它们组合起来,就是:
1 | |
params_type_desc 是什么
http-dubbo 并不是只根据 JSON 猜 Java 类型。
例如:
1 | |
Dubbo 方法参数是:
1 | |
它的 JVM Descriptor 是:
1 | |
所以配置:
1 | |
官方文档也建议使用 Dubbo 的:
1 | |
获取准确的类型描述,避免人工拼错。
例如:
1 | |
输出:
1 | |
对于:
1 | |
则是:
1 | |
这也是为什么直接改 Java 方法签名之后,APISIX Route 也可能需要同步更新。
为什么推荐一个 Request DTO,而不是多个参数
假设 Dubbo 接口设计成:
1 | |
那么 HTTP→Dubbo 层必须同时正确处理:
1 | |
http-dubbo 的预序列化调用方式要求每个参数按照 Dubbo 方法参数顺序组织;当前实现本身也是围绕 Dubbo 参数序列逐个构造请求。
因此更推荐:
1 | |
把:
1 | |
封装到:
1 | |
这样协议边界稳定得多:
1 | |
这不仅方便 APISIX,也让后续接口扩展更容易保持兼容。
调用订单 API
发送:
1 | |
整个链路是:
1 | |
业务返回内容取决于 Provider 实际实现。
Dubbo 3.x 下必须单独关注序列化兼容
这里是目前最容易出现“配置全部正确,但就是调用失败”的地方。
当前 http-dubbo 文档明确涉及 Dubbo 序列化约束,而插件实现自身也存在特定 Dubbo/Fastjson 编码逻辑。
与此同时,Dubbo 3.3 当前默认支持的主要序列化已经是:
1 | |
而不是早期的 legacy Fastjson;Dubbo 3.3 的默认序列化策略本身也发生过调整。
因此不能简单认为:
1 | |
生产环境必须做下面这个最小测试:
1 | |
至少验证:
1 | |
如果 Provider 使用的 Dubbo 版本、Serialization 与 APISIX 插件不兼容,不建议为了让网关能调用而强行降级到已经不推荐的旧序列化方式。
这种情况下,更合理的选择通常是:
1 | |
不要把“少一层 Adapter”看得比协议安全和稳定性还重要。
使用 dubbo-proxy 的兼容方案
如果已有 APISIX 环境具备 dubbo-proxy 所要求的 Dubbo Runtime,也可以继续采用早期实践中的方式。
订单 Route 可以写成类似:
1 | |
这个结构与早期 APISIX + Dubbo + Nacos Demo 基本一致:upstream 通过 Nacos 定位 Provider,dubbo-proxy 负责 Dubbo 调用。
不过当前 dubbo-proxy 官方文档明确注明了 OpenResty 构建要求,因此不能默认任意 APISIX 镜像都具备完整运行条件。
扩容第二个订单 Provider
现在启动两个订单实例:
1 | |
1 | |
或者本地测试:
1 | |
另一个:
1 | |
Nacos 中最终形成:
1 | |
APISIX Route 不需要改成:
1 | |
仍然保持:
1 | |
APISIX 刷新实例列表以后,就可以根据 Upstream 策略选择 Provider。
这才是:
1 | |
相比静态 Upstream 真正带来的价值。
Provider 下线时发生什么
假设:
1 | |
同时在线。
APISIX 当前缓存:
1 | |
此时停止:
1 | |
Dubbo Registry 更新 Nacos 实例状态,之后 APISIX 在下一轮服务发现刷新时获取新的 Provider 列表:
1 | |
随后新请求就不会继续依赖已经被移除的静态配置。
因此这里的关键参数:
1 | |
实际上决定了 APISIX 对注册中心变化的轮询刷新节奏。
它与应用自己的:
1 | |
是不同层面的机制。
Nacos Namespace 与 Group 怎么处理
生产环境一般至少存在:
1 | |
不应该让 APISIX 查询:
1 | |
APISIX Nacos Discovery 支持:
1 | |
当前 APISIX 文档中:
1 | |
默认对应 public Namespace,
1 | |
默认是:
1 | |
例如生产订单 Route:
1 | |
注册端必须进入同一个:
1 | |
否则现象通常是:
1 | |
因为它们实际上查询的不是同一个命名空间。
不要混淆 Nacos Group 与 Dubbo Service Group
这里还有两个名字非常容易混。
Nacos Group
例如:
1 | |
用于 Nacos 服务分类。
APISIX 对应:
1 | |
Dubbo Group
Dubbo Interface 本身还支持:
1 | |
此时 Service Key 会发生变化。
例如:
1 | |
它和 Nacos 的:
1 | |
不是一回事。
更麻烦的是,当前 http-dubbo 插件公开的配置 Schema 中没有与 Dubbo Service Group 完全对等的配置字段。
因此如果准备直接通过 APISIX 调 Dubbo,建议网关暴露的 Dubbo Facade 尽量避免再使用复杂的 Dubbo Group 路由。
版本隔离优先使用:
1 | |
会更容易控制。
订单接口版本升级怎么做
假设当前:
1 | |
准备上线:
1 | |
Nacos 中可以同时存在:
1 | |
以及:
1 | |
APISIX 可以分别配置:
1 | |
1 | |
例如:
1 | |
这里尤其要保证两个地方同时升级:
1 | |
以及:
1 | |
如果出现:
1 | |
但:
1 | |
最终通常只能得到非常难看的 RPC 异常。
下单接口不能照搬查询接口的重试策略
订单查询:
1 | |
通常属于只读请求。
而:
1 | |
属于写操作。
假设 APISIX 请求 Provider 后发生:
1 | |
就可能出现重复下单。
因此订单写接口至少需要业务级幂等键:
1 | |
服务端:
1 | |
而不是寄希望于:
1 | |
自动解决业务一致性。
对订单系统来说,应该明确:
1 | |
API Gateway 的网络可靠性机制不能替代业务幂等。
为什么不建议把所有 Dubbo 接口自动暴露出去
早期 APISIX + Dubbo + Nacos Demo 已经暴露出一个现实问题:
1 | |
如果全部手工创建 Route:
1 | |
维护成本会快速上升。
很自然会想到:
1 | |
技术上当然可以做。
但生产环境千万不要变成:
注册到 Nacos 的 Dubbo 接口自动全部开放公网。
因为内部 RPC 与外部 API 的安全边界完全不同。
例如:
1 | |
内部可能默认:
1 | |
如果机械暴露成:
1 | |
安全模型就被绕过了。
更合理的方式是维护白名单式 API Mapping:
1 | |
然后由 CI/CD:
1 | |
而不是:
1 | |
一个更合理的订单服务接口划分
如果确实准备让 APISIX 直接连接 Dubbo,可以专门设计 Gateway Facade。
不要直接暴露内部领域 Service:
1 | |
而是提供:
1 | |
形成:
1 | |
这样:
1 | |
与:
1 | |
之间仍然保留一层清晰的业务边界。
APISIX 消掉的是:
1 | |
而不是让:
1 | |
Docker 和 Kubernetes 环境最常见的问题:注册 IP 不可达
本地测试时:
1 | |
可能都在同一台机器。
到了 Docker 或 Kubernetes 里,经常出现:
1 | |
这时第一件事情不是查 APISIX Route,而是看 Nacos 返回的 IP。
例如:
1 | |
然后从 APISIX 所在网络测试:
1 | |
如果不通:
1 | |
实际上已经成功了。
失败的是:
1 | |
Docker
应确保:
1 | |
位于可以互通的 Docker Network。
Kubernetes
如果 Dubbo Provider 注册的是 Pod IP,则 APISIX 必须能够路由到对应 Pod CIDR。
如果:
1 | |
而 Provider 注册:
1 | |
这样的 Pod IP,外部 APISIX 很可能根本无法访问。
因此整个架构设计必须确保:
1 | |
而不是只看 Nacos 控制台显示:
1 | |
就认为网络没有问题。
Kubernetes 中推荐的网络关系
如果三个组件都部署在集群中:
flowchart TB
Ingress[External LoadBalancer]
APISIX[APISIX Pods]
Nacos[Nacos Cluster]
O1[Order Pod 1<br/>Dubbo 20880]
O2[Order Pod 2<br/>Dubbo 20880]
O3[Order Pod 3<br/>Dubbo 20880]
Ingress --> APISIX
APISIX -. Discovery .-> Nacos
O1 -. Register .-> Nacos
O2 -. Register .-> Nacos
O3 -. Register .-> Nacos
APISIX --> O1
APISIX --> O2
APISIX --> O3
这时候:
1 | |
负责 Dubbo Endpoint 的服务发现,
而不是让 APISIX 再通过:
1 | |
做第二层负载均衡。
否则可能形成:
1 | |
两层负载均衡叠在一起,反而失去了 APISIX 直接获取 Provider 实例的意义。
APISIX Admin API 不要暴露公网
教程为了方便通常直接:
1 | |
但生产环境的 Admin API 属于控制面。
能够访问它,就可能:
1 | |
所以至少应该:
1 | |
不要复制旧教程里的默认 Admin Key。
当前 APISIX 配置中,Admin Key 属于 deployment.admin.admin_key 等管理面配置,应按照当前版本安全配置管理,而不是继续沿用早期 Demo 的默认密钥。
例如:
1 | |
然后:
1 | |
而不是把密钥直接提交到:
1 | |
APISIX 与 Nacos 的账号也不要直接硬编码
开发环境可能:
1 | |
当前 APISIX Nacos Discovery 也支持包含认证信息的 Host 配置形式。
生产环境仍然更建议:
1 | |
不要:
1 | |
然后把整个文件提交到仓库。
可观测性应该怎么看
这条调用链至少涉及:
1 | |
排查问题时,建议把监控拆成三层。
Gateway
关注:
1 | |
例如:
1 | |
Service Discovery
关注:
1 | |
Dubbo
关注:
1 | |
最终要能把:
1 | |
定位到:
1 | |
否则一旦 APISIX 返回:
1 | |
很容易陷入:
1 | |
逐个猜的状态。
常见故障排查
| 现象 | 重点检查 |
|---|---|
| APISIX 404 | Route URI、Method 是否匹配 |
| No upstream node | Nacos Service Name、Namespace、Group |
| Nacos 有实例但 APISIX 找不到 | discovery_type、service_name、discovery_args |
| Dubbo 3 中只有 application service | register-mode 是否为 instance |
| Provider 连接失败 | Nacos 注册 IP、Dubbo Port、网络、防火墙 |
| 502 / Connection refused | APISIX 到 Provider 的 TCP 20880 是否可达 |
| Service not found | Interface、Version、Group 是否一致 |
| 参数反序列化失败 | params_type_desc、请求 Body、序列化方式 |
| Dubbo 3.3 调用异常 | APISIX 插件与 Dubbo Serialization 兼容性 |
| 扩容后迟迟没有流量 | Nacos 实例状态与 fetch_interval |
| Admin API 401/403 | Admin Key、管理面访问控制 |
No upstream node:先检查 Service Name
最典型错误:
1 | |
但实际使用的是接口级 Dubbo 注册:
1 | |
那么 APISIX 自然查不到。
检查:
1 | |
如果这里有数据,而:
1 | |
没有对应 Provider,就说明使用的是:
1 | |
Dubbo 3 Provider 根本没有 providers:* 怎么办
如果 Nacos 中只看到:
1 | |
看不到:
1 | |
很可能当前配置是:
1 | |
对于本文这种 APISIX 直接通过接口名称查询 Nacos 的方案,应改为:
1 | |
或者在只需要兼容接口发现的场景:
1 | |
但一般 Dubbo 3 系统中更推荐:
1 | |
作为迁移期间的兼容方案,而不是彻底退回接口级发现。Dubbo 官方目前仍明确区分 interface、instance 与 all 三种模式。
Nacos 有实例,但是 20880 连不上
先获取 Provider:
1 | |
在 APISIX 节点:
1 | |
如果:
1 | |
不要再继续研究:
1 | |
因为请求压根没有进入 Dubbo。
检查:
1 | |
排障一定要从 OSI 更低层开始。
Dubbo 能连上但反序列化失败
如果日志出现类似:
1 | |
重点看:
1 | |
例如 Java:
1 | |
配置却写:
1 | |
那协议层一定无法正常调用。
另外对于 Dubbo 3.x,要把:
1 | |
放到排障优先级非常高的位置,而不是默认认为“都是 Dubbo 协议,所以一定兼容”。当前 APISIX http-dubbo 实现和 Dubbo 3.3 默认序列化并非一个可以忽略版本差异的问题。
旧教程与当前实践的主要差异
| 项目 | 早期 APISIX + Dubbo + Nacos 示例 | 当前实践需要补充的内容 |
|---|---|---|
| APISIX | 2.x | 以当前 3.x 文档为准 |
| Nacos Discovery | service_name + discovery_type |
核心模型仍然适用 |
| Dubbo 注册 | 接口级 Provider | Dubbo 3 还存在应用级注册 |
| Nacos Service | providers:interface:version:group |
使用 register-mode=all/interface 才能稳定保留 |
| Dubbo 插件 | dubbo-proxy |
当前还可以评估 http-dubbo |
| 序列化 | 老版本通常更简单 | Dubbo 3.x 必须检查 Serialization |
| Admin API | Demo 默认 Key | 强密钥、私网、Secret 管理 |
| Route | 手工配置 | 可以 CI/CD 自动生成,但必须白名单控制 |
Nacos 服务发现本身的核心配置模型这些年变化并不大:
1 | |
真正变化最大的,是:
1 | |
因此迁移旧教程时,重点不应该只是把:
1 | |
机械替换成:
1 | |
而是重新验证整个协议边界。
哪些场景特别适合这种架构
比较适合:
1 | |
例如:
1 | |
这些接口:
1 | |
APISIX 直接调用 Dubbo 可以有效减少纯粹的 HTTP Adapter。
哪些场景不建议直接让 APISIX 调 Dubbo
例如首页接口:
1 | |
背后需要:
1 | |
如果试图全部放到 APISIX:
1 | |
API Gateway 很快就会变成:
1 | |
这不是一个好的边界。
这类场景依然适合:
1 | |
同样,订单提交可能需要:
1 | |
这些业务编排也应该留在:
1 | |
而不是塞进 APISIX 插件。
推荐的生产架构
如果确实需要 APISIX + Nacos + Dubbo,比较稳妥的方式是:
flowchart LR
Client[Client]
APISIX[APISIX]
Nacos[Nacos]
GatewayFacade[OrderGatewayFacade]
Application[Order Application Service]
Domain[Order Domain]
DB[(Order DB)]
Client -->|HTTP| APISIX
APISIX -. Nacos Discovery .-> Nacos
GatewayFacade -. Register .-> Nacos
APISIX -->|Dubbo| GatewayFacade
GatewayFacade --> Application
Application --> Domain
Domain --> DB
也就是说:
1 | |
只解决:
1 | |
订单服务继续解决:
1 | |
这样不会因为使用 APISIX 直连 Dubbo,就把网关变成业务系统。
推荐的配置管理方式
不要在大量 Route 中手工重复:
1 | |
可以抽象成 API Mapping:
1 | |
CI/CD 再生成 APISIX Route。
这样:
1 | |
而不是:
1 | |
生产环境真正重要的是:
1 | |
而不只是“能不能调通”。
一份实用的上线检查清单
上线前至少确认:
- Dubbo Provider 已正确注册到目标 Nacos Namespace。
- Nacos 中存在正确的
providers:interface:version:groupService。 - Dubbo 3 使用
register-mode=all或兼容的接口注册模式。 - APISIX 能访问 Nacos。
- APISIX 能从自身网络直接连接 Provider Dubbo Port。
service_name与 Nacos 中名称完全一致。- Dubbo Interface、Version、Method 完全一致。
params_type_desc已根据真实 Java 类型生成。- HTTP→Dubbo 插件与目标 Dubbo 版本的 Serialization 已经过真实测试。
- 写操作具有业务幂等机制。
- APISIX Admin API 不暴露公网。
- Admin Key 与 Nacos 凭证没有硬编码进 Git。
- Route 通过 Git/CI/CD 管理,而不是人工维护。
- API 只暴露经过审核的 Dubbo Facade。
- APISIX、Dubbo、Nacos 都具有可关联的日志和监控。
总结
APISIX + Nacos + Dubbo 的核心并不只是把三个中间件配置到一起,而是组合三种不同能力:
1 | |
完整链路可以概括为:
1 | |
真正需要记住三个工程细节。
第一,服务发现与协议转换是两回事。Nacos 只能告诉 APISIX Provider 在哪里,不能自动把 HTTP 请求变成 Dubbo RPC。
第二,Dubbo 3 的应用级服务发现改变了注册模型。如果 APISIX 仍然按 providers:interface:version:group 查询 Provider,就应该显式保留接口级注册,例如使用 register-mode: all。
第三,当前 Dubbo 3 的序列化体系与早期 APISIX Dubbo Demo 已经存在明显版本差异。Route 能创建成功、Nacos 能看到实例,都不能证明 HTTP→Dubbo 一定能够正确通信。协议插件、Dubbo 版本和 Serialization 必须作为一组进行兼容性测试。
对于订单系统,APISIX 直连 Dubbo 最适合查询类、简单 Command、稳定 Facade 等 1:1 API 映射场景。如果接口承担复杂业务编排、领域转换或跨服务聚合,保留 BFF 或 Adapter 并不是架构退步,反而能够保持 API 层和领域层之间清晰的边界。
参考资料
- 《APISIX + Dubbo + Nacos 最佳实践》,介绍了通过 APISIX 完成 HTTP/Dubbo 协议转换,并利用 Nacos 动态发现 Dubbo Provider 的整体方案。
- Nacos 官方《Apache APISIX 基于 Nacos 实现服务发现》,说明了 APISIX 使用
service_name、discovery_type=nacos动态构建 Upstream 的方式。 - Apache APISIX Nacos Service Discovery 当前文档,包括
discovery.nacos、fetch_interval、Namespace 和 Group 等配置。 - Apache APISIX
http-dubbo与dubbo-proxy文档及当前插件实现,用于理解 HTTP→Dubbo 协议转换、方法描述和运行时要求。 - Apache Dubbo Nacos Registry 与服务发现资料,用于理解 Dubbo 3 的应用级/接口级注册模式及 Nacos Service Name。