本页面适用于 Apigee 和 Apigee Hybrid。
查看 Apigee Edge 文档。
本文档提供了一套使用 Apigee 开发 API 代理的最佳做法。
此处涉及的主题包括设计、编码、政策使用、监控和调试。这些信息是根据与 Apigee 合作的开发者成功实施 API 项目的经验收集的。这是一个活动文档,会不时更新。
除了上述指南之外,您还可以了解反模式简介。
开发标准
注释和文档
- 在
ProxyEndpoint
和TargetEndpoint
配置中提供内嵌注释。注释增强了流的可读性,特别是在政策文件名不足以描述流的基本功能的情况下。 - 提交有用的注释。避免显而易见的注释。
- 使用一致的缩进、间距、垂直对齐等。
框架式编码
框架式编码涉及将 API 代理资源存储在您自己的版本控制系统中,以便在本地开发环境中重复使用。例如,要重复使用某项政策,请将其存储在源代码控制系统中,以便开发者能够与其同步,并在自己的代理开发环境中使用该政策。
- 为了实现 DRY(避免重复代码)原则,在可能的情况下,政策配置和脚本应实施专门的、可重复使用的功能。例如,从请求消息中提取查询参数的专用政策可以称为
ExtractVariables.ExtractRequestParameters
。 - 清理 API 代理中未使用的政策和资源(JavaScript、Java、XSLT),尤其是那些可能会减慢导入和部署过程的大型资源。
命名规则
- 政策
name
属性和 XML 政策文件名必须相同。 - 脚本和 ServiceCallout 政策的
name
属性和资源文件名应相同。 DisplayName
应向从未使用过该 API 代理的用户准确描述政策的功能。- 根据政策的功能为其命名。Apigee 建议您为自己的政策建立一致的命名规则。例如,使用简短前缀,后跟一系列由短划线分隔的描述性单词。例如,AssignMessage 政策使用
AM-xxx
。另请参阅 apigeelint 工具。 - 对资源文件使用适当的扩展名,对 JavaScript 使用
.js
,对 Python 使用.py
,对 Java JAR 文件使用.jar
。 - 变量名称应保持一致。如果您选择一种样式(例如:camelCase 或 under_score),请在整个 API 代理中使用该样式。
- 请尽可能使用变量前缀来根据其用途组织变量,例如
Consumer.username
和Consumer.password
。
API 代理开发
初始设计注意事项
- 如需了解有关 RESTful API 设计的指导,请下载电子书 《网络 API 设计:缺失的环节》(Web API Design: The Missing Link)。
- 尽可能利用 Apigee 政策和功能来构建 API 代理。避免对 JavaScript、Java 或 Python 资源中的所有代理逻辑进行编码。
- 以有条理的方式构建流。使用多个流(每个流一个条件)比为同一个 PreFlow 和 Postflow 关联多个条件更可取。
- 作为“故障安全机制”,使用
/
的 ProxyEndpoint BasePath 创建一个默认 API 代理。这可用于将基本 API 请求重定向到开发者网站、返回自定义响应,或者执行比返回默认messaging.adaptors.http.flow.ApplicationNotFound
更有用的其他操作。 - 为了实现最佳性能,Apigee 建议对每个 Apigee 环境或环境组使用的 API 代理基本路径数量不超过 3,000 个。如果超出此建议值,可能会导致所有新的和现有 API 代理部署的延迟时间增加。
- 使用 TargetServer 资源将 TargetEndpoint 配置与具体网址分离开来,从而支持跨环境的升级。
请参阅跨后端服务器的负载平衡。 - 如果您有多个 RouteRules,请创建一个作为“default”,即没有条件的 RouteRule。确保在条件路由列表中最后定义默认 RouteRule。ProxyEndpoint 中的 RouteRule 以自上而下的顺序评估。 请参阅 API 代理配置参考。
- API 代理软件包大小:API 代理软件包的大小不能超过 15MB。
- API 版本控制:如需了解 Apigee 对 API 版本控制的看法和建议,请参阅《网络 API 设计:缺失的环节》(Web API Design: The Missing Link) 电子书中的版本控制。
启用 CORS
在发布 API 之前,您需要将 CORS 政策添加到 ProxyEndpoint 的请求 PreFlow 中,以支持客户端跨源请求。
CORS(跨源资源共享)是一种标准机制,允许在网页中执行的 JavaScript XMLHttpRequest (XHR) 调用与来自非源网域的资源进行交互。CORS 是所有浏览器强制执行的同源政策一种常用解决方案。例如,如果您从浏览器执行的 JavaScript 代码向 Twitter API 发出 XHR 调用,则该调用将失败。这是因为为浏览器提供网页的网域与为 Twitter API 提供服务的网域不同。CORS 针对这个问题提供了一个解决方案,允许服务器在希望提供跨域资源共享的情况下“选择加入”。
如需了解如何在发布 API 之前在 API 代理上启用 CORS,请参阅向 API 代理添加 CORS 支持。
消息负载大小
为了防止 Apigee 中出现内存问题,消息负载大小上限为 10MB。超出大小上限会导致 protocol.http.TooBigBody
错误。
使用 Apigee 代理请求/返回大型负载时发生错误中也讨论了此问题。
以下是在 Apigee 中处理大型消息大小的推荐策略:
- 流式传输请求和响应。请注意,在您执行流式传输操作时,政策不再有权访问消息内容。请参阅流式传输请求和响应。
故障处理
- 利用 FaultRules 处理所有故障处理。(RaiseFault 政策用于停止消息流并将处理发送到 FaultRules 流。)
- 在 FaultRules 流中,使用 AssignMessage 政策来构建故障响应,而不是使用 RiseFault 政策。根据发生的故障类型有条件地执行 AssignMessage 政策。
- 始终包含默认的“catch-all”故障处理程序,以便系统生成的故障可以映射到客户定义的故障响应格式。
- 如果可能,请始终让故障响应与您的公司或项目中可用的任何标准格式匹配。
- 使用可针对错误情况提出解决方案的、有意义且易于理解的错误消息。
请参阅处理故障。
持久性
键/值映射
- 仅对有限的数据集使用键/值映射。它们不是为长期数据存储而设计的。
- 在使用键/值映射时,请考虑性能,因为此信息存储在 Cassandra 数据库中。
响应缓存
- 如果响应失败或者请求不是 GET,请勿填充响应缓存。不应缓存创建、更新和删除。
<SkipCachePopulation>response.status.code != 200 or request.verb != "GET"</SkipCachePopulation>
- 使用一种一致的内容类型(例如 XML 或 JSON)填充缓存。检索 responseCache 条目后,使用 JSONtoXML 或 XMLToJSON 转换为所需的内容类型。这可防止存储两倍、三倍或更多的数据。
- 请确保缓存键足以满足缓存要求。在许多情况下,
request.querystring
可用作唯一标识符。 - 除非明确要求,否则请勿在缓存键中包含 API 密钥 (
client_id
)。大多数情况下,对于给定请求,仅受密钥保护的 API 会向所有客户端返回相同的数据。根据 API 密钥为多个条目存储相同的值效率很低。 - 设置适当的缓存到期间隔以避免脏读。
- 请尽可能晚地在 ProxyEndpoint 响应 PostFlow 上执行填充缓存的响应缓存策略。换句话说,让其在平移和中介步骤之后执行,包括基于 JavaScript 的中介以及 JSON 和XML 之间的转换。通过缓存中介数据,您可以避免在每次检索缓存数据时执行中介步骤的性能成本。
请注意,如果中介导致请求与请求之间的响应不同,您可能需要缓存未中介的数据。
- 用于查找缓存条目的响应缓存政策应出现在 ProxyEndpoint 请求 PreFlow 中。在返回缓存条目之前,请避免实现过多逻辑,而不是缓存密钥生成。否则,缓存的优势将减至最低。
- 通常,您应该始终让响应缓存查找尽可能靠近客户端请求。相反,您应该让响应缓存填充尽可能靠近客户端响应。
- 在代理中使用多项不同的响应缓存政策时,请遵循以下准则,以确保每种政策的行为都是独立的:
- 根据互斥条件执行每项政策。这有助于确保只执行多个响应缓存政策中的一个。
- 为每个响应缓存政策定义不同的缓存资源。您可以在政策的
<CacheResource>
元素中指定缓存资源。
请参阅 ResponseCache 政策。
政策和自定义代码
政策还是自定义代码?
- 首先(在可能的情况下)使用内置政策。Apigee 政策经过了加强、优化和支持。例如,使用标准 AssignMessage 政策和 ExtractVariables 政策而不是 JavaScript(如果可能)来创建载荷,从载荷(XPath、JSONPath 等)提取信息等等。
- 相较于 Python 和 Java,建议使用 JavaScript。不过,如果性能是主要要求,则应使用 Java 而非 JavaScript。
JavaScript
- 如果 JavaScript 比 Apigee 政策更直观(例如,为许多不同的 URI 组合设置
target.url
时),请使用 JavaScript。 - 复杂的负载解析,例如迭代 JSON 对象和 Base64 编码/解码。
- JavaScript 政策具有时间限制,因此无限循环会被屏蔽。
- 始终使用 JavaScript 步骤并将文件放入
jsc
资源文件夹中。 JavaScript 政策类型会在部署时预编译代码。
Java
- 如果性能是最高优先级,或者无法在 JavaScript 中实现逻辑,请使用 Java。
- 在源代码跟踪中收录 Java 源文件。
如需了解如何在 API 代理中使用 Java 的信息,请参阅 JavaCallout 政策。
Python
- 除非绝对需要,否则请勿使用 Python。Python 脚本可能会为简单的执行带来性能瓶颈,因为它在运行时会被解释。
脚本标注(Java、JavaScript、Python)
- 使用全局 try/catch 或等效方法。
- 抛出有意义的异常,并正确捕获这些异常,以便在故障响应中使用。
- 尽早抛出并捕获异常。请勿使用全局 try/catch 来处理所有异常。
- 必要时执行 null 和未定义的检查。例如,在检索可选流变量时执行此操作。
- 避免在脚本标注中发出 HTTP/HTTPS 请求。相反,请使用 ServiceCallout 政策,因为该政策可以很好地处理连接。
JavaScript
- API 平台上的 JavaScript 通过 E4X 支持 XML。
请参阅 JavaScript 对象模型。
Java
- 访问消息负载时,尝试使用
context.getMessage()
与context.getResponseMessage
或context.getRequestMessage
。这可以确保代码在请求和响应流中均可检索负载。 - 将库导入 Apigee 组织或环境,并且不将它们包含在 JAR 文件中。这可减小软件包大小,并允许其他 JAR 文件访问同一个库代码库。
- 使用 Apigee 资源 API 导入 JAR 文件,而不是将其包含在 API 代理资源文件夹中。这将减少部署时间,并允许多个 API 代理引用相同的 JAR 文件。另一个好处是类加载器隔离。
- 请勿使用 Java 进行资源处理(例如,创建和管理线程池)。
Python
- 抛出有意义的异常,并正确捕获这些异常,以便在 Apigee 故障响应中使用
请参阅 PythonScript 政策。
ServiceCallouts
- 有许多使用代理链的有效用例,您可以在一个 API 代理中使用服务标注来调用其他 API 代理。如果您使用代理链,请确保避免无限循环递归调用返回同一 API 代理。
如果您要连接在同一组织和环境中的代理,请务必查看将 API 代理链接在一起,详细了解如何实现本地连接,以避免不必要的网络开销。
- 使用 AssignMessage 政策构建 ServiceCallout 请求消息,并将请求对象填充到消息变量中。(包括设置请求负载、路径和方法。)
- 在政策中配置的网址需要协议规范,这意味着,网址的协议部分不能通过变量指定,例如
https://
。此外,您还必须对网址的网域部分和网址的其余部分使用单独的变量。例如:https://example.com
。 - 将 ServiceCallout 的响应对象存储在单独的消息变量中。然后,您可以解析消息变量并使原始消息负载保持不变,以供其他政策使用。
请参阅 ServiceCallout 政策。
访问实体
AccessEntity 政策
- 为了获得更好的性能,请按
uuid
(而不是应用名称)查找应用。
请参阅 AccessEntity 政策。
日志记录
- 在多个软件包之间和同一软件包中使用相同的 syslog 政策。这将保持一致的日志记录格式。
请参阅 MessageLogging 政策。
监控
Cloud 客户无需检查 Apigee 的单个组件(路由器,消息处理器等)。根据客户的健康检查请求,Apigee 的全球运营团队全面监控所有组件以及 API 健康检查。
Apigee 分析
衡量错误百分比时,分析可以提供非关键 API 监控。
请参阅分析信息中心。
调试
Apigee 界面中的跟踪工具可用于在 API 的开发或生产操作期间调试运行时 API 问题。
请参阅使用调试工具。
安全
- 使用 IP 地址限制政策来限制对测试环境的访问。允许访问开发机器或环境的 IP 地址,并禁止其他所有 IP 地址。请参阅 AccessControl 政策。
- 始终对部署到生产的 API 代理应用内容保护政策(JSON 和 XML)。请参阅 JSONThreatProtection 政策。
- 如需了解更多关于安全性方面的最佳做法,请参阅以下主题:
API 代理中的自定义逻辑
构建 API 代理时的一项常见要求是添加一些用于处理请求和/或响应的逻辑。虽然可以通过一组预定义的步骤/操作/政策(例如验证令牌、应用配额或使用缓存对象进行响应)来满足许多要求,但通常可能需要具备编程能力。例如,根据请求中找到的密钥从路由表中查找位置(端点),并动态应用目标端点或自定义/专有身份验证方法等。
Apigee 为开发者提供了处理此类自定义逻辑的多个选项。本文档将介绍这些选项以及何时使用哪些选项:
政策 | 政策用例 |
---|---|
JavaScript 和 PythonScript |
何时使用:
不适用情形:
最佳做法:Apigee 推荐使用 JavaScript 而不是 PythonScript,因为 JavaScript 的性能更佳。 |
JavaCallout |
何时使用:
不适用情形:
|
ExternalCallout |
何时使用:
未使用时:
|
ServiceCallout |
何时使用:
未使用时:
|
总结:
- 如果逻辑简单或无关紧要,请使用 JavaScript(最好)或 PythonScript。
- 如果内嵌逻辑的性能要求高于 JavaScript 或 PythonScript,请使用 JavaCallout。
- 如果逻辑必须外部化,请使用 ExternalCallout。
- 如果您已有外部实现和/或开发者熟悉 REST,请使用 ServiceCallout。
下图演示了此流程: