一、背景与目标

大多数企业的核心业务系统基于 Dubbo 微服务架构构建,服务之间通过 Dubbo RPC 协议通信。而新一代 AI Agent 平台(如 DeerFlow)则以 HTTP API 对外暴露能力。

这就产生了一个架构鸿沟:

┌─────────────┐     Dubbo RPC     ┌──────────────┐     HTTP     ┌──────────────┐
│  业务系统 A  │ ────────────────▶ │  业务系统 B   │              │  AI Agent    │
│  (OA 系统)   │                  │  (财务系统)    │              │  (DeerFlow)  │
└─────────────┘                  └──────────────┘              └──────────────┘
                                    ↑ 传统 Dubbo 通信              ↑ 仅暴露 HTTP

⚠️ 这篇文章不是教你怎么接一个大模型 API 然后写死几个业务场景。 市面上大多数所谓的"AI 集成"就是在 Controller 里写 if-else 调一下 OpenAI,场景写死、能力固定、扩展困难。

我们做的是:底层 Harness 全栈能力支撑 + Skills 插件式架构 + Agent 自主规划执行。

  • 不是简单 HTTP 透传,Identity Guardrail 权限控制、Sandbox 执行隔离、Skills 插件系统、MCP 协议,全部保留
  • 不是写死场景,每个业务域一个 SKILL.md,Agent 自主读文档、自主规划、自主调接口
  • 不是玩具,是企业级的安全可控

二、项目架构概览

我们构建了四个模块:

java-simple-dubbo-app/
├── dubbo-api/              # 公共 Dubbo 接口和 DTO
│   ├── FinanceService.java      # 财务系统接口
│   └── QuickFlowService.java    # AI Agent 接口
├── finance-system/          # 财务系统 — Dubbo Provider
│   └── FinanceServiceImpl.java  # @DubboService 实现
├── oa-system/               # OA 系统 — Dubbo Consumer
│   ├── OaBizService.java        # → Dubbo → Finance
│   ├── OaAiService.java         # → Dubbo → QuickFlow Adapter
│   └── OaAiController.java     # 含业务意图识别+数据拼接
└── quickflow-adapter/       # 协议转换层 — Dubbo Provider
    └── QuickFlowServiceImpl.java # Dubbo → HTTP → DeerFlow

端口分配

服务 HTTP 端口 Dubbo 端口
finance-system 8082 20880
oa-system 8081
quickflow-adapter 8083 20881
DeerFlow Gateway 2026 (Nginx)

三、三种集成模式

模式 A:Dubbo 直连(传统业务服务间通信)

OA 系统通过 @DubboReference(url = "dubbo://localhost:20880") 直连财务系统。

完整链路:

浏览器 → OA HTTP (8081)
         → @DubboReference → Finance Service (20880)
         → 查询报销单/校验预算
         → 返回 Mock 数据
// OA 侧 — Dubbo Consumer
@DubboReference(url = "dubbo://localhost:20880")
private FinanceService financeService;

public ReimburseResponse queryReimburse(String reimburseNo, String applicantId) {
    return financeService.queryReimburse(new ReimburseRequest(reimburseNo, applicantId));
}

模式 B:Dubbo → HTTP 协议转换(AI Agent 集成)

这是最核心的模式。OA 系统只认 Dubbo 协议,DeerFlow 只暴露 HTTP API,中间需要一个协议转换层。

OA 系统 (Dubbo Consumer)
  │ @DubboReference(url = "dubbo://localhost:20881")
  ▼
QuickFlow Adapter (Dubbo Provider + HTTP Client)
  │ WebClient POST → /api/runs/wait
  ▼
DeerFlow Gateway (FastAPI, port 2026)
  │ DeepSeek / OpenAI
  ▼
AI 回复

为什么需要这个适配器层?

  • OA 系统是纯 Dubbo 体系,没有 HTTP Client 的依赖和管理
  • 适配器可以集中管理 API Token、超时、重试等配置
  • 适配器可以被多个业务系统复用(一篇适配,多处调用)
  • 未来如果 DeerFlow 升级或更换,只改适配器即可
@DubboService
public class QuickFlowServiceImpl implements QuickFlowService {

    @Value("${quickflow.base-url}")
    private String baseUrl;

    @Value("${quickflow.api-token}")
    private String apiToken;

    private WebClient webClient;

    @Override
    public ChatResponse chat(ChatRequest request) {
        // 1. 构建 DeerFlow 请求体
        ObjectNode body = mapper.createObjectNode();
        body.putNull("assistant_id");  // 使用默认 Agent

        // 2. 调用 DeerFlow HTTP API
        String jsonResponse = webClient.post()
            .uri("/api/runs/wait")
            .bodyValue(body)
            .retrieve()
            .bodyToMono(String.class)
            .block();

        // 3. 解析返回的 messages,提取 AI 文本回复
        return parseResponse(jsonResponse, conversationId);
    }
}

模式 C:Intent Resolver(Java 层先查数据再喂给 AI)

如果老系统不暴露接口,或者你希望更可控,可以在 Java Controller 层做意图识别 + 数据预查:

@PostMapping("/chat")
public ResponseEntity<?> chat(@RequestBody Map<String, String> request) {
    String message = request.get("message");

    // 意图识别:如果包含报销单号
    Pattern pattern = Pattern.compile("RE\\d{9}");
    Matcher matcher = pattern.matcher(message);
    if (matcher.find()) {
        // 自己查数据
        String reimburseNo = matcher.group();
        ReimburseResponse data = financeService
            .queryReimburse(new ReimburseRequest(reimburseNo, null));

        // 把数据拼进去,再发给 AI
        message = message + "\n\n[系统查询结果]\n" + JSON.toJSONString(data);
    }

    // 发给 AI
    return oaAiService.chat(message, conversationId);
}

模式 C 的价值:数据不出内网、意图识别可控、AI 只做 NLG。

四、安全设计

4.1 API Token — 调用方身份认证

DeerFlow 通过 API Token 认证调用方。Token 可以关联到具体租户或用户:

Authorization: Bearer dft_xxx

设计要点:Token 绑定到具体权限范围;只暴露 AI Agent 调用能力;可单独吊销。

4.2 Org Key — 数据隔离与资源控制

┌──────────────────────────────────────────────────────┐
│                    DeerFlow Gateway                    │
│  API Token → 身份认证 → 获取 Org/User Identity        │
│  Identity → Identity Guardrail → 权限校验             │
│    ↓                                                    │
│  skill:invoke  → 可以调用 skills + 工具                │
│  thread:read   → 可以读取当前线程                      │
│  thread:write  → 可以创建/修改线程                     │
│  无权限 → 返回 authz.tool.denied                      │
└──────────────────────────────────────────────────────────┘

DeerFlow 的权限模型基于 Identity Guardrail,每次工具调用前检查权限,不在白名单中的工具默认拒绝(default-deny)。

4.3 序列化安全

Dubbo 默认使用 Hessian2 序列化。在跨版本通信时需要配置序列化白名单:

dubbo:
  security:
    serialize:
      allowlist: com.dubbo.demo, java.util, java.lang
  • DTO 必须实现 Serializable + 固定 serialVersionUID
  • dubbo-api 用最低 JDK 版本编译,双方共用

4.4 服务隔离

安全维度 实现方式
网络隔离 Adapter 作为唯一对外暴露节点,内网 Dubbo 服务不暴露公网
权限最小化 Adapter 只暴露 AI 需要的接口,不暴露完整的 Dubbo 服务
调用审计 可在 Adapter 层记录所有 AI 发起的请求
限流控制 可在 Adapter 层配置 QPS 限制

五、前端集成

OA 系统在右下角加入浮动聊天机器人。AI 在对话过程中会根据 SKILL.md 自主决定调什么接口:

用户: "销售部申请15000预算够吗?"
→ AI 识别意图 → 读 SKILL.md
→ 发现可用 Adapter HTTP 接口
→ 主动调 GET /api/finance/budget/check?deptId=DEPT_SALES&amount=15000
→ 获取数据,回复"预算充足,剩余10万"

用户: "查一下报销单 RE202607001 的状态"
→ AI 识别出报销单号
→ 调 GET /api/finance/reimburse?reimburseNo=RE202607001
→ 回复"已审批,张三差旅费¥12,800.50"

用户: "帮我写一段出差申请"
→ AI 判断无需调接口 → 直接输出申请模板

一切由 AI 自主规划,不是预先写死的 if-else。

六、JDK 8 兼容性说明

分层策略:让 Adapter 升级,让业务系统保持不变

核心思路:Adapter 升级到 JDK 17+,业务系统保持 JDK 8。

┌──────────────────────────────┐
│  OA 系统 (JDK 8)             │  ← 不改
│  Dubbo 2.7.x                 │
└──────────┬───────────────────┘
           │ Dubbo RPC(跨版本兼容)
           ▼
┌──────────────────────────────┐
│  QuickFlow Adapter (JDK 21)  │  ← 升级
│  Dubbo 3.x + Spring Boot 3.x  │
└──────────────────────────────┘

Dubbo 2.7.x 和 3.x 使用相同的 dubbo:// 协议,底层 Hessian2 序列化兼容。

七、实际运行效果

# 启动三个服务
java -jar finance-system/target/finance-system-1.0.0.jar
java -jar quickflow-adapter/target/quickflow-adapter-1.0.0.jar
java -jar oa-system/target/oa-system-1.0.0.jar

# 验证链路
curl "http://localhost:8083/api/finance/reimburse?reimburseNo=RE202607001"
curl -X POST http://localhost:8081/api/oa/ai/chat \
  -H "Content-Type: application/json" \
  -d '{"message":"查一下 RE202607001","conversationId":"test"}'

八、集成模式对比与选型建议

模式 适用场景 老系统改动 数据流向 AI 自主度
A: Dubbo 直连 传统业务服务间通信 ❌ 零改动 纯内网 无 AI 参与
B: Protocol Adapter Dubbo 系统调 HTTP AI ❌ 零改动 AI 主动调
C: Intent Resolver 业务可控优先 ❌ 零改动 先查再送

九、Scale Up:从 Adapter 到 Sidecar 的架构演进

当前 Adapter 的三个瓶颈

中心化 Adapter 解决了从 0 到 1 的问题,但量上来后会面临:单点故障、接口膨胀、部署耦合。

Sidecar 模式:去中心化的答案

Sidecar 借用了 Istio/Envoy 的经典架构思路——把基础设施能力从中心抽出来,推到每个业务系统旁边

改造前:
OA 服务器                 Adapter 服务器(瓶颈!)
┌──────────┐   Dubbo     ┌────────────┐   HTTP    ┌──────────┐
│ OA       │ ──────────▶ │ Adapter    │ ────────▶ │ DeerFlow │
│ (8081)   │             │ (8083)     │           │ (2026)   │
└──────────┘  经过网络    └────────────┘           └──────────┘

改造后(Sidecar):
OA 服务器
┌─────────────────────────────────────┐
│  OA 进程                             │
│  @DubboReference(url="dubbo://       │
│     localhost:20081")                │ ← 本机 Sidecar
└────────────┬────────────────────────┘
             │ Dubbo(本地回环,不走网络)
             ▼
┌─────────────────────────────────────┐
│  AI Sidecar                          │
│  - 本地缓存(Caffeine)               │
│  - 熔断器(Resilience4j)             │
│  - 无状态,随业务系统自动扩缩          │
│     ↓ HTTP                           │
│  DeerFlow                            │
└──────────────────────────────────────┘

Sidecar 对比中心化 Adapter

维度 中心化 Adapter Sidecar
部署位置 一台独立服务器,所有系统共用 跟业务系统同机,一一对应
实例数量 1 个(单点) N 个(随业务系统数量)
故障影响 挂了 = 所有系统失去 AI 能力 只影响挂了的那台机器
调用延迟 网络 RTT(0.5~2ms) 本地回环(0.01~0.1ms)

从 Adapter 到 Sidecar 的平滑迁移

第 1 步:Sidecar 跟 Adapter 共存,灰度切流
第 2 步:全部切到 Sidecar
第 3 步:Adapter 退役,控制面上线(控制面只做配置下发,不参与数据面)

整个过程 OA 系统代码一行不改——QuickFlowService 接口不变,只改 url。

十、代码结构

java-simple-dubbo-app/
├── dubbo-api/                      # 公共接口(JDK 8 可编译)
├── finance-system/                 # 财务系统 — 老系统模拟
├── quickflow-adapter/              # 协议转换层 — 唯一新服务
└── oa-system/                      # OA 系统

十一、不止 Dubbo:Adapter 模式的普适规律

我们用 Dubbo 做了完整示例,但这个模式不限于 Dubbo。gRPC、SOAP/WebService、ESB 总线、甚至银行核心用的 IBM MQ 和 Tuxedo——思路完全一样,只是底层协议实现不同。

核心规律

不管底层是什么协议,Adapter 做的事始终只有三件:

老系统 → [协议 A] → Adapter → [HTTP JSON] → AI Agent
                       ↓
                 1. 连上老系统(用老系统的协议)
                 2. 拿到数据(解析老系统的响应格式)
                 3. 转成 HTTP JSON(暴露给 AI)

唯一变化的是第 1 步和第 2 步。第 3 步永远是 HTTP JSON。

各协议对比

老系统协议 怎么连 解析复杂度 常见行业
Dubbo @DubboReference 直连 Provider 互联网、企业应用
gRPC grpc-client-spring-boot-starter 云原生微服务
SOAP/WebService WebServiceTemplate 或 CXF 银行、金融、政府
ESB 总线 接入 ESB 的对外接口 大型企业核心系统
IBM MQ JMS 客户端 银行核心交易

银行 SOAP + ESB 场景拆解

AI → Adapter(HTTP → SOAP 转换)→ ESB(不变)→ 核心系统

已经有 ESB 了为什么还要加 Adapter?因为 ESB 和 Adapter 定位完全不同:

维度 ESB(已有) Adapter(新增)
服务对象 业务系统间通信(高 TPS) AI 零星查询(几分钟一次)
接口粒度 完整交易接口(几十个字段) 精简查询(3-5 个参数)
变更门槛 以月为单位 以天为单位
安全模型 ESB 自有认证 API Token + Org Key

代码对比:Dubbo vs SOAP

// Dubbo Adapter
@DubboReference(url = "dubbo://localhost:20880")
private FinanceService financeService;

@GetMapping("/api/finance/reimburse")
public Map<String, Object> queryReimburse(@RequestParam String no) {
    ReimburseResponse resp = financeService.queryReimburse(new ReimburseRequest(no));
    return Map.of("code", 0, "data", resp);
}
// SOAP Adapter(同一套思路,换协议)
@Autowired
private WebServiceTemplate wsTemplate;

@GetMapping("/api/bank/account")
public Map<String, Object> queryBalance(@RequestParam String accountNo) {
    QueryBalanceRequest req = new QueryBalanceRequest();
    req.setAccountNo(accountNo);
    QueryBalanceResponse resp = (QueryBalanceResponse)
        wsTemplate.marshalSendAndReceive("http://esb:9080/QueryBalance", req);
    return Map.of("code", 0, "data", Map.of("balance", resp.getBalance()));
}

两个 Adapter 的区别只在于:第 1 行注解方式不同、URL 格式不同。剩下 90% 的代码——Controller 结构、错误处理、返回格式——完全一样。

部署位置权衡

部署方式 适用协议 优缺点
同进程嵌入 Dubbo、SOAP(客户端轻) ✅ 延迟最低 ❌ 依赖 JDK 版本
边车 Sidecar gRPC、Thrift ✅ 协议与业务解耦 ❌ 多一跳
对接 ESB SOAP、JMS ✅ ESB 不改 ❌ 依赖 ESB 团队
独立网关 多种协议混合 ✅ 统一入口 ❌ 架构复杂

不值得做 Adapter 的判断标准

如果 AI 一周都问不到一次这个系统的数据,就别接。

十二、总结

本文通过一个完整的 Java Dubbo 示例项目,展示了企业级微服务集成 AI Agent 的三种模式:

  1. Dubbo 直连 — 传统业务服务间通信
  2. Protocol Adapter — Dubbo 体系调用 HTTP 服务的标准模式
  3. Intent Resolver — 业务侧先查数据再喂给 AI

同时覆盖了企业级安全设计(API Token、序列化安全、QoS)、JDK 8 兼容方案、Sidecar 大规模演进路线,以及不同协议(gRPC、SOAP、ESB、MQ)的普适规律。

整套方案的核心理念是:对现有系统零侵入,通过边缘适配器逐步引入 AI 能力。

你们不需要知道 AI 的存在。不需要改任何代码。不需要升级 JDK。 你们的 Dubbo 服务正常跑就行。Adapter 会主动来连你们。

完整示例代码:java-simple-dubbo-app