如何在 Apigee X 中使用 ServiceCallout 和 FlowCallout 进行编排?
Source: Dev.to
在 Apigee X 中使用 ServiceCallout / FlowCallout 进行编排的方式
在 API 管理平台中,编排(orchestration) 通常指的是在单个 API 流程中调用多个后端服务、聚合响应或执行业务逻辑。Apigee X 为此提供了两种主要的策略(policy):
- ServiceCallout – 用于向外部 HTTP/HTTPS 服务发起请求并获取响应。
- FlowCallout – 用于在同一代理内部调用另一个 flow(即另一个 API 代理或同一代理中的子流程),从而实现更细粒度的复用。
下面将分别介绍这两种策略的使用场景、配置要点以及示例代码。
1. ServiceCallout
何时使用
- 需要调用 外部 REST、SOAP 或 GraphQL 服务。
- 想要在请求/响应链路中 插入自定义请求头、查询参数或请求体。
- 需要对返回的 状态码、响应体 进行检查或转换。
基本配置
<ServiceCallout name="SC-GetCustomerInfo">
<Request variable="customerRequest">
<Set>
<Headers>
<Header name="Authorization">Bearer {access_token}</Header>
</Headers>
<Payload>{request.content}</Payload>
</Set>
</Request>
<Response>customerResponse</Response>
<HTTPTargetConnection>
<URL>https://api.example.com/customers/{customerId}</URL>
</HTTPTargetConnection>
</ServiceCallout>
要点
variable用于保存发送的请求对象。Response指定返回结果保存的变量名(后续可在 AssignMessage、JavaScript 等策略中使用)。HTTPTargetConnection中的 URL 可以使用 Apigee 变量(如{customerId})进行动态拼接。
常见用法
| 用例 | 示例 |
|---|---|
| 聚合多个后端 | 先使用 ServiceCallout 调用 订单服务,再调用 库存服务,最后在 JavaScript 中合并结果。 |
| 错误处理 | 检查 customerResponse.status,若为 4xx/5xx 则抛出 RaiseFault。 |
| 缓存 | 将响应写入 ResponseCache,后续请求直接命中缓存。 |
2. FlowCallout
何时使用
- 需要在 同一代理内部 重用已有的 flow(例如公共的身份验证、日志记录或审计流程)。
- 想要把复杂的业务逻辑拆分成 可组合的子流程,保持主流程的可读性。
- 想要在 不同的 API 代理之间共享 统一的实现(通过 Shared Flow)。
基本配置
<FlowCallout name="FC-ValidateToken">
<FlowName>ValidateTokenFlow</FlowName>
<Input>
<Variable name="access_token" value="{request.header.Authorization}"/>
</Input>
<Output>
<Variable name="tokenValid" value="{ValidateTokenFlow.tokenValid}"/>
</Output>
</FlowCallout>
要点
FlowName必须是当前代理或 Shared Flow 中已经定义的 flow 名称。Input用于向子 flow 传递变量,Output用于把子 flow 产生的变量返回到父 flow。
常见用法
| 用例 | 示例 |
|---|---|
| 统一身份验证 | 所有 API 都调用同一个 ValidateTokenFlow,只需在每个代理中放置一个 FlowCallout。 |
| 审计日志 | 将日志写入外部系统的逻辑封装在 AuditLogFlow 中,主流程只需要调用一次。 |
| 条件路由 | 根据子 flow 的返回值(如 tokenValid)决定是否继续执行后续策略。 |
3. 组合使用示例
下面的示例展示了在 订单查询 场景中,先使用 FlowCallout 完成 令牌校验,随后使用 ServiceCallout 调用 订单服务 与 客户服务,最后在 JavaScript 中聚合响应。
<!-- 1. 令牌校验 -->
<FlowCallout name="FC-Auth">
<FlowName>ValidateTokenFlow</FlowName>
<Input>
<Variable name="access_token" value="{request.header.Authorization}"/>
</Input>
<Output>
<Variable name="isValid" value="{ValidateTokenFlow.isValid}"/>
</Output>
</FlowCallout>
<!-- 2. 若令牌无效则抛错 -->
<RaiseFault name="RF-InvalidToken" enabled="{!isValid}">
<FaultResponse>
<Set>
<Headers>
<Header name="Content-Type">application/json</Header>
</Headers>
<Payload>{"error":"Invalid token"}</Payload>
</Set>
<StatusCode>401</StatusCode>
<ReasonPhrase>Unauthorized</ReasonPhrase>
</FaultResponse>
</RaiseFault>
<!-- 3. 调用订单服务 -->
<ServiceCallout name="SC-GetOrder">
<HTTPTargetConnection>
<URL>https://orders.api.example.com/orders/{orderId}</URL>
</HTTPTargetConnection>
<Response>orderResponse</Response>
</ServiceCallout>
<!-- 4. 调用客户服务 -->
<ServiceCallout name="SC-GetCustomer">
<HTTPTargetConnection>
<URL>https://customers.api.example.com/customers/{orderResponse.customerId}</URL>
</HTTPTargetConnection>
<Response>customerResponse</Response>
</ServiceCallout>
<!-- 5. 聚合结果 -->
<JavaScript name="JS-Aggregate">
<ResourceURL>jsc://aggregate.js</ResourceURL>
</JavaScript>
aggregate.js(保持原样,不翻译):
var order = JSON.parse(context.getVariable('orderResponse.content'));
var customer = JSON.parse(context.getVariable('customerResponse.content'));
var result = {
orderId: order.id,
amount: order.amount,
customerName: customer.name,
customerEmail: customer.email
};
context.setVariable('response.content', JSON.stringify(result));
4. 性能与最佳实践
| 建议 | 说明 |
|---|---|
| 尽量使用 FlowCallout 复用 Shared Flow | 可以把公共的安全、日志、限流等逻辑抽离为 Shared Flow,减少重复配置。 |
| 对外部调用使用缓存 | 对不经常变化的数据(如产品目录)使用 ResponseCache,降低 ServiceCallout 的网络开销。 |
| 限制并发调用 | 当同一请求需要并行调用多个后端时,使用 Parallel(Apigee X 支持的 Async)策略,避免阻塞。 |
| 错误传播 | 在 ServiceCallout 之后立即检查 response.status,必要时使用 RaiseFault 将错误返回给调用方。 |
| 监控与日志 | 在关键节点(如 FlowCallout 前后)加入 MessageLogging,便于在 Apigee Analytics 中追踪调用链。 |
5. 小结
- ServiceCallout 适用于 外部 HTTP/HTTPS 调用,能够灵活设置请求头、负载以及处理返回。
- FlowCallout 更适合 内部复用(Shared Flow 或同一代理的子 flow),帮助实现 模块化 与 统一治理。
- 两者可以 组合 使用,实现从 身份验证 → 多后端聚合 → 响应组装 的完整编排流程。
- 通过合理的 缓存、错误处理、监控,可以在保持灵活性的同时,确保系统的 高可用性 与 低延迟。
Tip: 在 Apigee X 中,建议把所有公共的安全与审计逻辑封装为 Shared Flow,并通过 FlowCallout 引入。这样既能保持代理的简洁,又能在全平台统一管理这些关键功能。
介绍
想象这样一种情况:客户端调用一个 API,但在后台你的后端必须:
- 调用 客户服务
- 调用 订单服务
- 调用 支付服务
- 合并所有响应
- 向客户端返回一个干净的响应
如果让后端处理所有这些逻辑,它很快就会变得慢、耦合紧密且难以维护。这正是 Apigee X 发挥作用的地方。它位于你的后端系统前面,充当智能流量控制器:
- 管理 API 代理
- 强制执行安全策略
- 控制流量
- 编排多个后端调用
你将学到
在本指南结束时,你将了解:
- API 编排的真正含义
- 何时使用 ServiceCallout 与 FlowCallout
- 如何在 Apigee X 中组合多个后端调用
- 避免常见编排错误的最佳实践
本指南适合初学者,实用且已准备好发布。
API Orchestration Analogy
把 API 编排想象成餐厅的服务员:
- 您(客户端) 下单一次。
- 服务员 与厨房、甜点柜台和结账处沟通。
- 您收到一盘最终的菜品。
Apigee X 就是那个服务员,协调多个后端服务。
API 代理概述
在 Apigee X 中,API 代理是一层:
- 接收客户端请求
- 应用安全、配额和转换
- 与后端服务通信
- 将响应返回给客户端
客户端不需要调用多个服务,而是调用单一的代理。
ServiceCallout 与 FlowCallout 对比
| 特性 | ServiceCallout | FlowCallout |
|---|---|---|
| 目的 | 调用外部 REST/SOAP 服务 | 执行内部辅助逻辑(JS,共享流) |
| 典型用例 | 从其他服务获取数据 | 复用策略、JavaScript、共享流 |
示例:客户摘要代理
单个 API 必须返回客户详情和订单摘要。其内部实现如下:
- 调用 Customer API
- 调用 Order API
- 合并响应
- 发送最终响应
客户端请求: GET /customer-summary
Client → Apigee X → Multiple Backends → Final Response
ServiceCallout – 获取客户
<ServiceCallout name="GetCustomer">
<Request>
<Set>
<Verb>GET</Verb>
<Path>/customers/{customerId}</Path>
</Set>
</Request>
<Response>customerResponse</Response>
<HTTPTargetConnection>
<URL>https://backend-customer-api</URL>
</HTTPTargetConnection>
</ServiceCallout>
发生了什么?
Apigee 调用 Customer API;响应被存储在 customerResponse 中。此时客户端尚未参与。
ServiceCallout – 获取订单
<ServiceCallout name="GetOrders">
<Request>
<Set>
<Verb>GET</Verb>
<Path>/orders/{customerId}</Path>
</Set>
</Request>
<Response>orderResponse</Response>
<HTTPTargetConnection>
<URL>https://backend-order-api</URL>
</HTTPTargetConnection>
</ServiceCallout>
现在 Apigee 同时拥有 客户数据 和 订单数据。
FlowCallout – 合并响应
<FlowCallout name="CombineResponses">
<SharedFlow>combine-response-flow</SharedFlow>
</FlowCallout>
共享流内部(JavaScript):
var customer = JSON.parse(context.getVariable("customerResponse.content"));
var orders = JSON.parse(context.getVariable("orderResponse.content"));
var finalResponse = {
customer: customer,
orders: orders
};
context.setVariable("response.content", JSON.stringify(finalResponse));
结果: 单个干净的响应返回给客户端,客户端并不知道背后有多个后端调用。
最佳实践
- 保持编排轻量化 – 不要把 Apigee 变成完整的后端替代品。
- 使用共享流复用逻辑 – 非常适合 FlowCallout。
- 优雅地处理失败 – 对后端超时使用
FaultRules。 - 谨慎设置超时 – 多次调用会增加延迟风险。
- 监控性能 – 编排会增加处理时间。
- 记录中间响应 以便排查问题。
常见错误避免
- ❌ 进行过多的顺序 ServiceCallout 调用。
- ❌ 硬编码后端 URL。
- ❌ 忽视超时和重试策略。
- ❌ 在 Apigee 中嵌入大量业务逻辑。
- ❌ 未记录中间响应。
结论
- ServiceCallout – 与外部后端进行交互。
- FlowCallout – 用于复用和处理逻辑。
此模式可以帮助您:
- 减少客户端复杂性
- 提升 API 一致性
- 在网关实现集中控制
它在 API 管理、微服务和企业集成中被广泛使用。