Salesforce Composite API 深度解析:为集成工程师打造的高效事务性API利器

背景与应用场景

大家好,我是一名 Salesforce 集成工程师。在我的日常工作中,核心任务是将各种外部系统(如 ERP、营销自动化平台、电子商务网站等)与 Salesforce 进行无缝对接。在这个过程中,API 调用是我们的主要工具。然而,传统的集成模式常常面临一个棘手的挑战:网络延迟(Network Latency)事务完整性(Transactional Integrity)

想象一个常见的业务场景:当一个新客户在我们的电子商务网站上注册并下了第一笔订单时,我们需要在 Salesforce 中执行一系列操作:

  1. 创建一个新的客户 (Account) 记录。
  2. 基于新创建的客户,创建一个联系人 (Contact) 记录。
  3. 为该客户创建一个新的订单 (Order) 记录。
  4. 为该订单添加多个订单项 (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 请求体。我们设置了 allOrNonetrue 以启用事务模式。

{
    "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:

  • allOrNonetrue 时,如果任何子请求失败,整个请求将返回一个 HTTP 400 Bad Request 状态码,响应体中会包含导致失败的第一个子请求的详细错误信息。此时,你可以确定没有任何数据被提交到数据库。
  • allOrNonefalse 时,情况变得复杂。即使有子请求失败,整个 Composite API 调用也可能返回 HTTP 200 OK 状态码。你必须遍历响应体中的 compositeResponse 数组,逐一检查每个子响应的 httpStatusCode。任何非 2xx 的状态码(如 400, 404, 500)都表示该子请求失败,其 body 中会包含错误详情。你的代码逻辑必须能够处理这种部分成功的场景。

其他限制

  • referenceId 只能引用在同一次 Composite 调用中、排在它前面的子请求的结果。不能跨 Composite 调用引用,也不能引用排在它后面的子请求。
  • 并非所有 REST API 资源都支持在 Composite API 中调用。通常,用于操作 sObject 记录的资源(创建、更新、删除、查询)是支持的,但一些特殊的管理类 API 可能不支持。请务必查阅相关文档。

总结与最佳实践

对于我们集成工程师而言,Salesforce Composite API 是一个功能强大且不可或缺的工具。它通过捆绑请求和提供事务控制,完美地平衡了性能和数据完整性。

最佳实践总结如下:

  1. 优先用于处理关联记录: 当你需要执行一系列有依赖关系的操作时(如创建主记录和其子记录),Composite API 是首选方案。
  2. 明确事务需求: 根据业务逻辑仔细选择 allOrNone 的值。对于需要保证数据一致性的核心业务流程,坚决使用 true
  3. 设计健壮的错误处理逻辑: 无论 allOrNone 如何设置,都要准备好解析复合响应体,并对每个子请求的成功或失败状态进行处理。
  4. 避免滥用: Composite API 不适用于大规模数据加载。当需要处理成千上万条记录时,请使用为该场景专门设计的 Bulk API,以获得更好的性能和资源利用率。
  5. 监控 API 消耗: 始终记住,每个子请求都会消耗 API 调用次数。在设计集成方案时,要将其纳入 API 使用量的整体规划中。

总而言之,熟练掌握和运用 Composite API,将使你的 Salesforce 集成方案更加高效、可靠和优雅,从而在复杂的系统对接挑战中游刃有余。

评论

此博客中的热门博文

Salesforce Einstein AI 编程实践:开发者视角下的智能预测

Salesforce 登录取证:深入解析用户访问监控与安全

Salesforce Experience Cloud 技术深度解析:构建社区站点 (Community Sites)