Salesforce Composite API 深度解析:为集成工程师打造的高效事务性API利器
背景与应用场景
大家好,我是一名 Salesforce 集成工程师。在我的日常工作中,核心任务是将各种外部系统(如 ERP、营销自动化平台、电子商务网站等)与 Salesforce 进行无缝对接。在这个过程中,API 调用是我们的主要工具。然而,传统的集成模式常常面临一个棘手的挑战:网络延迟(Network Latency)和事务完整性(Transactional Integrity)。
想象一个常见的业务场景:当一个新客户在我们的电子商务网站上注册并下了第一笔订单时,我们需要在 Salesforce 中执行一系列操作:
- 创建一个新的客户 (Account) 记录。
- 基于新创建的客户,创建一个联系人 (Contact) 记录。
- 为该客户创建一个新的订单 (Order) 记录。
- 为该订单添加多个订单项 (Order Line Items)。
如果使用标准的 REST API,我们需要为上述每个步骤都发起一次独立的 HTTP 请求。这意味着至少需要 4 次(如果只有一个订单项)网络往返。这种方式不仅效率低下,增加了服务器的负担,更重要的是,它无法保证数据的一致性。如果在创建订单项时发生错误,而客户和订单已经成功创建,我们就会在系统中留下不完整的“孤儿”数据,后续的数据清理和补偿逻辑会变得非常复杂。
正是为了解决这类问题,Salesforce 提供了 Composite API。作为一名集成工程师,我视它为应对复杂、多步骤数据操作的“瑞士军刀”。它允许我们将最多 25 个子请求(subrequests)捆绑在一个单一的 API 调用中,从而显著减少网络往返次数,并能以原子事务的方式执行这些操作,确保“要么全部成功,要么全部失败”,极大地保障了数据的完整性。
原理说明
Salesforce Composite API 的核心思想非常直观:将多个独立的 API 请求聚合成一个复合请求体(JSON 格式),然后通过一次 HTTP POST 请求发送到 Salesforce。Salesforce 服务器在接收到这个复合请求后,会按顺序处理其中的每一个子请求,并将所有子请求的结果聚合成一个复合响应体返回给客户端。
其强大的功能主要体现在以下两个关键特性上:
1. 事务控制 (Transactional Control) - allOrNone
在复合请求的根级别,有一个布尔类型的属性 allOrNone。这个属性是 Composite API 的精髓所在。
- 当
allOrNone设置为true时,整个复合请求将作为一个原子事务(Atomic Transaction)执行。这意味着,只要其中任何一个子请求失败,Salesforce 会自动回滚(Rollback)在该次复合请求中已经成功执行的所有数据库操作。最终结果是,要么所有子请求都成功提交,要么所有操作都像从未发生过一样被撤销。这完美地解决了我们之前提到的数据一致性问题。
- - 当
allOrNone设置为false时,各个子请求将被独立处理。即使某个子请求失败,也不会影响其他子请求的成功提交。这种模式适用于那些彼此之间没有强依赖关系、允许部分成功的批量操作。
2. 请求间依赖引用 (Inter-request Dependencies) - referenceId
这是 Composite API 另一个天才般的设计。在很多业务流程中,后续操作往往依赖于前面操作的结果。例如,创建联系人时,需要先获取到其所属客户的 ID。在传统模式下,我们必须先发起创建客户的请求,等待响应返回客户 ID,然后再用这个 ID 构造创建联系人的请求并发起第二次调用。
Composite API 通过 referenceId 机制优雅地解决了这个问题。我们可以在一个子请求中定义一个唯一的 referenceId(一个自定义的字符串),然后在同一个复合请求的后续子请求中,使用特殊的语法 @{referenceId.id} 来引用该子请求成功创建记录的 ID。Salesforce 会在处理时动态地将这个占位符替换为真实的记录 ID。这使得我们可以在一次调用中完成对关联记录的完整创建流程,极大地简化了集成逻辑。
示例代码
让我们通过 Salesforce 官方文档中的一个经典示例,来直观地感受 Composite API 的强大之处。以下代码演示了如何在一个请求中同时创建一个客户 (Account) 和一个关联的联系人 (Contact),并确保它们要么都成功,要么都失败。
示例请求 (Request)
这是一个发送到 /services/data/v58.0/composite 端点的 HTTP POST 请求体。我们设置了 allOrNone 为 true 以启用事务模式。
{
"allOrNone": true,
"compositeRequest": [
{
"method": "POST",
"url": "/services/data/v58.0/sobjects/Account",
"referenceId": "refAccount",
"body": {
"Name": "Salesforce"
}
},
{
"method": "POST",
"url": "/services/data/v58.0/sobjects/Contact",
"referenceId": "refContact",
"body": {
"LastName": "Johns",
"AccountId": "@{refAccount.id}"
}
}
]
}
代码注释:
- 第 2 行:
"allOrNone": true- 开启事务模式。如果创建 Account 成功但创建 Contact 失败,那么 Account 的创建也会被回滚。 - 第 3 行:
"compositeRequest": [...]- 这是复合请求的主体,一个包含所有子请求的 JSON 数组。 - 第 5-10 行: 第一个子请求,用于创建一个新的 Account。
"method": "POST"- 指定 HTTP 方法。"url": "..."- 指定子请求的目标 API 端点。"referenceId": "refAccount"- 为这个子请求定义一个引用 ID,名为 "refAccount",以便后续请求使用。"body": { "Name": "Salesforce" }- 请求体,包含要创建的 Account 的字段和值。
- 第 11-17 行: 第二个子请求,用于创建一个新的 Contact。
"referenceId": "refContact"- 为这个子请求定义一个独立的引用 ID。"AccountId": "@{refAccount.id}"- 这是关键!我们使用@{refAccount.id}语法来引用第一个子请求(由 "refAccount" 标识)成功执行后返回结果中的 `id` 字段。Salesforce 会在执行时自动填充新创建的 Account ID。
示例响应 (Response)
如果上述请求成功执行,你将收到一个 HTTP 200 OK 状态码,以及类似下面的响应体:
{
"compositeResponse": [
{
"body": {
"id": "001xx000003DHPxAAO",
"success": true,
"errors": []
},
"httpHeaders": {
"Location": "/services/data/v58.0/sobjects/Account/001xx000003DHPxAAO"
},
"httpStatusCode": 201,
"referenceId": "refAccount"
},
{
"body": {
"id": "003xx000004WfV3AAK",
"success": true,
"errors": []
},
"httpHeaders": {
"Location": "/services/data/v58.0/sobjects/Contact/003xx000004WfV3AAK"
},
"httpStatusCode": 201,
"referenceId": "refContact"
}
]
}
响应解析:
"compositeResponse": [...]- 响应体的主体,一个 JSON 数组,其顺序和内容与请求中的compositeRequest数组一一对应。- 第 3-13 行: 第一个子请求的响应结果。
"body"中包含了子请求的执行结果,包括新记录的id。"httpStatusCode": 201表示“已创建”,是 POST 请求成功的标准状态码。"referenceId": "refAccount"将此响应与请求中的 "refAccount" 子请求关联起来。
- 第 14-24 行: 第二个子请求的响应结果,结构类似。
注意事项
作为集成工程师,在使用 Composite API 时,必须牢记以下几点,以确保集成的稳定和高效:
权限 (Permissions)
执行 Composite API 的用户必须拥有对所有子请求中涉及的对象和字段的相应权限(CRUD/FLS)。例如,在上面的示例中,用户需要同时拥有创建 Account 和 Contact 的权限,以及对 Name、LastName 和 AccountId 字段的写入权限。权限不足是导致子请求失败的常见原因。
API 限制 (API Limits)
- 子请求数量限制: 一次 Composite API 调用最多可以包含 25 个子请求。
- API 调用计数: 这非常重要!虽然你只发起了一次 HTTP 请求,但在计算 Salesforce 的 API 调用限制时,每一个子请求都会被计为一次独立的 API 调用。因此,一个包含 5 个子请求的 Composite 调用,会消耗 5 次 API 调用额度。它节省的是网络往返时间,而不是 API 调用总数。
- 数据量限制: 与其他 REST API 一样,Composite API 的请求体大小也有限制。请避免在一次调用中传递过大的数据负载。对于大规模数据迁移或加载,应优先选择 Bulk API。
错误处理 (Error Handling)
错误处理是集成工作中至关重要的一环。对于 Composite API:
- 当
allOrNone为true时,如果任何子请求失败,整个请求将返回一个 HTTP 400 Bad Request 状态码,响应体中会包含导致失败的第一个子请求的详细错误信息。此时,你可以确定没有任何数据被提交到数据库。 - 当
allOrNone为false时,情况变得复杂。即使有子请求失败,整个 Composite API 调用也可能返回 HTTP 200 OK 状态码。你必须遍历响应体中的compositeResponse数组,逐一检查每个子响应的httpStatusCode。任何非 2xx 的状态码(如 400, 404, 500)都表示该子请求失败,其body中会包含错误详情。你的代码逻辑必须能够处理这种部分成功的场景。
其他限制
referenceId只能引用在同一次 Composite 调用中、排在它前面的子请求的结果。不能跨 Composite 调用引用,也不能引用排在它后面的子请求。- 并非所有 REST API 资源都支持在 Composite API 中调用。通常,用于操作 sObject 记录的资源(创建、更新、删除、查询)是支持的,但一些特殊的管理类 API 可能不支持。请务必查阅相关文档。
总结与最佳实践
对于我们集成工程师而言,Salesforce Composite API 是一个功能强大且不可或缺的工具。它通过捆绑请求和提供事务控制,完美地平衡了性能和数据完整性。
最佳实践总结如下:
- 优先用于处理关联记录: 当你需要执行一系列有依赖关系的操作时(如创建主记录和其子记录),Composite API 是首选方案。
- 明确事务需求: 根据业务逻辑仔细选择
allOrNone的值。对于需要保证数据一致性的核心业务流程,坚决使用true。 - 设计健壮的错误处理逻辑: 无论
allOrNone如何设置,都要准备好解析复合响应体,并对每个子请求的成功或失败状态进行处理。 - 避免滥用: Composite API 不适用于大规模数据加载。当需要处理成千上万条记录时,请使用为该场景专门设计的 Bulk API,以获得更好的性能和资源利用率。
- 监控 API 消耗: 始终记住,每个子请求都会消耗 API 调用次数。在设计集成方案时,要将其纳入 API 使用量的整体规划中。
总而言之,熟练掌握和运用 Composite API,将使你的 Salesforce 集成方案更加高效、可靠和优雅,从而在复杂的系统对接挑战中游刃有余。
评论
发表评论