Salesforce 集成几乎从来不是败在协议上。认证是已经解决的问题,写入一条记录也是已经解决的问题。真正把项目拖垮的,是每天的请求配额和数据模型的形状,而这两件事通常要等到上线大约三周之后才被发现,那时夜间作业开始返回错误,却没有人说得清它在测试环境里为什么是好的。
这个模式一致到可以预测。开发者对着一个 Developer Edition 组织开发,一切通过,客户签字验收。随后这套代码遇上的,是一个已经住着营销连接器、数据仓库抽取作业和一个 2019 年就在跑的 Apex 触发器的生产组织,而那份看起来很宽裕的请求预算,其实是别人早已在花的一口共用的锅。
这篇文章把意外提前摊开来讲:你应该用哪个 API、配额是怎么算的、当你的写入触发了不是你写的代码会发生什么、认证发生了什么变化,以及哪些数据模型决定一旦做错就很难回头。
决定一个 Salesforce 集成成败的是什么? 是配额和数据模型,不是协议。每天的 API 请求配额是组织级的,由版本和许可证数量推导出来,所以一个规规矩矩的集成完全可能被同一组织里另一个写得很糟的集成饿死。从第一行代码起就按批处理来设计,在写入任何东西之前先把外部 ID 和 upsert 谈定,并且默认你发出的每一条记录都会触发别人的 Apex。
Salesforce 集成必须做对的事
有四件,而且分量并不相同。
第一件是配额。你的代码发出的每一次同步调用,都从一个组织级的、每天只有一份的配额里扣除,这份配额与该组织的所有其他使用方共享。
第二件是底下的平台。Salesforce 不是一个带 HTTP 接口的数据库。它是一个应用平台,你的写入会执行由管理员配置的触发器、流程、验证规则、重复规则和汇总字段,而那些管理员从来没听说过你的项目。
第三件是数据模型。Lead、Contact、Account 和 Opportunity 并不能互换,它们之间的转换是单向的且带有副作用,选错了就不是改代码,而是做数据迁移。
第四件是身份:你的系统和 Salesforce 如何就"哪条记录是哪条"达成一致。这一点错了,重复数据会以机器的速度生成。后面所有内容,都从这四件中的某一件延伸出来。
API 全景,以及你真正需要哪一个
Salesforce 公开了一个庞大的 API 家族。权威清单是 Salesforce API 索引,下面这些名字来自它,而不是来自记忆。
REST API 与 SOAP API
REST API 是所有记录形状工作的默认选择:创建、读取、更新、删除、查询、describe。网页表单写入一个 Lead、门户读取某个客户尚未关闭的案例,以及任何低流量的交互路径,用它都是对的。
SOAP API 通过 WSDL 做同样的事,它至今仍然存活,因为大量企业中间件天生就说这门话,也因为它给你一份可以据以生成客户端的强类型契约。人们常犯的错误,是认定 SOAP 是遗留而 REST 是现代。两者都是现行的,而且 SOAP 的 create() 和 update() 每次各接受最多 200 条记录,这件事比线上格式重要得多。
Bulk API 2.0
Bulk API 2.0 是处理量的异步作业式通道。你上传一个 CSV,Salesforce 在后台把它切块并处理,你轮询结果。Salesforce 的 Bulk API 限制允许滚动的 24 小时内最多 15,000 个批次、同一窗口内最多摄入 1.5 亿条记录,作业文件上限为 150 MB。
人们常犯的错误,是把 Bulk 当成以后再调优的一步。它是另一种编程模型:结果异步返回、按记录返回,你的代码从一开始就必须按那种方式消费它们。
Composite 与 sObject Collections
这两者是 REST API 里价值最高、也最少被使用的部分。一个 composite 请求在单次调用中最多可带 25 个子请求,其中最多 5 个可以是查询或 sObject Collections 操作,而且靠后的子请求可以引用靠前的子请求返回的 ID。sObject Collections 在一次请求里最多处理同一对象的 200 条记录。两者对每日配额都只算 一次调用,这正是它们的意义所在。
人们常犯的错误,是根本不知道它们存在。先建 Account、再建 Contact、再建 Opportunity 这样三次顺序调用,花掉的配额是一次 composite 请求的三倍,延迟也是三倍。
Streaming、变更数据捕获与 Pub/Sub
Streaming API 是基于 CometD 的订阅通道,服务于 PushTopic、通用事件、平台事件和变更事件。变更数据捕获在记录被创建、更新、删除或恢复时发布近实时通知,让外部存储不必轮询就能跟上 Salesforce。Platform Events 则是你自己定义的事件。
Pub/Sub API 是更新的 gRPC 与 HTTP/2 接口,把发布、订阅、模式获取和主题发现合并进一个 API,负载用 Avro 而不是 JSON。如果是新建的事件驱动实现,从它开始。
人们常犯的错误,是把事件当成有保证的数据流。它们并不能取代对账,原因在下一节。
API 请求限制才是真正的约束
这一节决定你的架构,而它通常是在设计完成之后才被读到的那一节。
每日配额是怎么算出来的
Salesforce 的 API 请求限制文档按版本和许可证数量设定配额,而不是按用户或按应用。带 API 访问权的 Enterprise 和 Professional 版本获得 100,000 次调用,外加每个 Salesforce 或 Salesforce Platform 许可证 1,000 次。Unlimited 和 Performance 版本获得 100,000 次,外加每个许可证 5,000 次。Developer Edition 一律 15,000 次,而一个 Full 沙箱是 5,000,000 次。
由此得出两点。一个 60 用户的 Enterprise 组织每天大约有 160,000 次调用,不是无限供应。而既然配额由许可证推导而来,提高它的方法就只有两个:买更多用户许可证,或者买额外的 API 调用,两者都通过 Salesforce 的 Your Account 应用购买。
什么会被计入,用完之后会怎样
配额按 24 小时内对该组织的所有调用总量来衡量,把 REST API、SOAP API、Bulk API、Bulk API 2.0 以及大多数 Connect REST API 调用一并计入。来自某些 Salesforce 连接应用的调用,例如移动应用,则被排除在外。
正是这种汇总把人绊住。你的集成没有自己的预算。它和报表连接器、营销平台以及这个组织里的每一个其他集成共用同一份预算,而一个每三十秒轮询一次的糟糕使用方,就足以把它抽干,饿死那些表现完全正常的代码。
当组织超出配额时,请求会以 403 和 REQUEST_LIMIT_EXCEEDED 失败。Salesforce 会允许付费生产组织有一定程度的超额,然后才硬性执行,但试用组织和 Developer Edition 没有这种宽限。请按没有宽限来设计。
在定下设计之前先测量
在写代码之前,先从管理员那里拿到该组织的配额和当前每日消耗量,REST API 有一个组织限制资源可以查。如果现有使用方已经用掉了 70%,那么逐条记录的同步集成就是不可行的,调优也救不回来。
批处理是设计决定,不是优化项
一旦你接受配额是有限且共享的,设计就会自己长出来。
不要用循环去做单条记录的调用。一个逐条创建 5,000 个 Contact 的作业会花掉 5,000 次调用。同样这 5,000 条,走 sObject Collections、每次请求 200 条,只花 25 次。这个 200 倍的系数,就是一个集成塞得进中型组织的配额与塞不进的分界线。
当工作是一张图而不是一个列表时,用 Composite。在一次请求里创建父记录和它的子记录,既省掉往返,也省掉你的代码在等待 ID 时不得不保存的中间状态。
任何更像加载或导出而不像事务的工作,用 Bulk API 2.0。它不适合交互路径,因为它按设计就是异步的,不会给用户一个同步的答案。
缓存参考数据。选项列表值、记录类型 ID 和 describe 结果很少变化,却在每次运行时被毫无理由地重新获取。仅这一项改动,往往就能砍掉一个天真实现的四分之一调用量。
调控器限制:你的写入会运行别人的代码
Salesforce 在严格的单事务上限内执行客户编写的 Apex。对集成真正有影响的 Apex 调控器限制是:每个同步事务 100 条 SOQL 查询、SOQL 取回 50,000 条记录、150 条 DML 语句、DML 处理 10,000 条记录、10 秒同步 CPU 时间,以及 6 MB 堆内存。
那些 Apex 不是你写的。你照样会撞上这些限制,因为你入站的写入会开启一个事务,运行该对象上存在的任何触发器。
不写 Apex 也要懂的批量化
即便你从不打开一个 Apex 文件,这个概念也值得理解。
Salesforce 交给触发器的是一组记录,而不是一条。写得正确的触发器用一次查询和一次更新处理整组记录。按照"每次只会收到一条记录"来写的触发器,则是每条记录跑一次查询和一次更新。
第二种触发器会完美工作很多年,因为用户是通过界面一条一条保存记录的。然后你的集成在一次请求里发来 200 条,触发器把它的查询跑了 200 遍,冲破 100 条查询的上限,整个批次失败。
Bulk API 2.0 以 200 条记录为一块来处理摄入数据,每一块是一个独立事务,所以这不是理论问题。它就是首次向一个有历史的组织做批量加载时的标准形态。
该怎么应对
在答应交付日期之前,先审计你将要写入的每一个对象上的触发器和流程。如果某个触发器没有做批量化,就得有人去修,而那个人需要 Apex 能力和一个部署窗口。把它作为一个预算条目列出来。
如果修复超出范围,就把批次调小。每次请求 200 条是上限而不是要求,降到 50 条有时能腾出足够余量先上线,同时排期去做触发器的改造。这会吃配额,所以要把它当成临时措施。
明年还能用的认证方式
这个领域发生了实质性变化,很多已发布的指南现在是错的。
OAuth 2.0 的用户名密码流程是要避开的那一个。它把凭据直接暴露在请求里,Salesforce 在较新的组织中默认封锁它,而且它在连接应用上的退役也已排期。任何还在使用它的集成,都需要一份带日期的迁移计划。
对于没有人参与其中的服务器到服务器工作,当前的两个答案是:用证书为断言签名的 JWT 承载流程,以及用消费者密钥和密钥换取令牌的客户端凭据流程。Salesforce 关于用集成用户和客户端凭据调用 REST API的说明明确指出,这个流程不签发刷新令牌,所以旧令牌过期后由客户端去请求一个新的访问令牌。
连接应用与外部客户端应用
承载这一切的容器过去是连接应用。现在是外部客户端应用。Salesforce 明确表示从 Spring ‘26 起连接应用的创建受到限制,并推荐改用外部客户端应用,把它描述为为提升安全性、解决打包问题而设计的新一代。
如果你的集成文档写着"创建一个连接应用",那它描述的是一条新组织可能不再提供的路径。在确定工作范围之前,先确认目标组织适用哪一种。
用专用集成用户运行,并为轮换做计划
给集成一个自己的用户,配最小访问权限、仅 API 的简档。不要以某位在职员工的身份运行它。当那位员工离职、账号被停用时,集成就停了,而且是在最糟的时刻停的,报出的错误还指不到任何有用的地方。
证书会过期,密钥会轮换。两者在出事那天之前都是安静的,而且两者都会让集成整体下线,而不是部分下线。把到期日放进由某个人负责的日历里,把凭据放进密钥管理器里,并且在真正需要之前先在沙箱里演练一次轮换。
数据模型的陷阱
这些是会花掉三周的陷阱,因为撤销它们意味着搬数据,而不是改代码。
Lead、Contact、Account 与 Person Account
Lead 是尚未与公司记录关联的未验证潜在客户。Contact 是挂在 Account 下的人。Account 是一个组织。转换会把一个 Lead 变成一个 Account 和一个 Contact,可选地再加一个 Opportunity,而 SOAP 的 convertLead 调用明确说明只有目标上为空的字段才会被写入,所以你精心填好的 Lead 字段未必会落到你以为的位置。
Person Account 让事情更复杂。面向消费者的组织会启用它,让一个个人同时以 Account 和 Contact 的合体形式存在,于是按企业 Account 模型写的集成,在启用了它的组织里不做改动就跑不通。这一点被发现得晚,规律得让人沮丧。
某条入站记录该变成哪个对象,要和业务方以书面形式定下来。这不是一个技术决定。
外部 ID 与 upsert
这是 Salesforce 给你的唯一一个讲道理的幂等机制,应该当成没有商量余地的东西。在对象上建一个标记为外部 ID 的自定义字段,把你自己系统的主键存进去。之后你就可以用 upsert 操作,也就是对 /sobjects/{Object}/{ExternalIdField}/{Value} 发起的 PATCH:没有匹配时创建记录,恰好匹配到一条时更新它。零匹配返回 201,一条匹配返回 200,多条匹配则以 300 失败而不是去猜。
后果值得直说。有了 upsert,重试一个失败的请求是安全的。没有它,每一次重试都是一个潜在的重复记录,而夜间作业中一次短暂的网络抖动,就会变成以天计的清理工作。
会在你写入时触发的规则
重复规则可以拦截或提醒你的集成创建的记录。验证规则会拒绝不满足管理员所配置条件的记录。必填字段可能在你上线几个月之后才被加上,从那一刻起,一个本来正常的集成开始在每一条记录上失败。
这些都不是缺陷,它们是这个组织按配置运转的样子。错误在于把一次被拒绝的写入当成传输错误并永远重试,而正确的反应是把它连同字段级的原因一起呈现给人。我们关于第三方 API 集成的成本与失败模式的指南,在别处讨论了同一类问题。
错误处理、幂等性与重放
一个没有重放机制的集成,会变成人工数据修复工作。这不是预言,这就是会发生的事。
部分成功是常态。sObject Collections 的 allOrNone 默认为 false,所以一个 200 条记录的请求可能返回 187 条成功和 13 条失败,每条各带原因,Bulk API 2.0 同样按记录返回结果。只检查外层 HTTP 状态码的代码,会一边悄悄丢掉记录一边报告成功。
在重试之前先给失败分类。行锁、超时和配额耗尽这类瞬时状况值得指数退避。验证错误和缺少必填字段这类确定性失败会永远以同样的方式失败,重试它们只是在烧你本来就不宽裕的配额。
每一条无法恢复的记录都要连同它的负载和错误进入死信存储,供人检查并重新提交。因为你的写入以外部 ID 为键,重新提交是安全的。把你的标识符与 Salesforce ID 的对应关系在两侧都记录下来;六个月后,那份日志会是唯一能解释某个客户的记录为什么不对的东西。
还要对账。平台事件和变更事件在事件总线上保留 72 小时,而 Salesforce 的平台事件配额把每日投递上限定为 Enterprise 25,000 个事件、Unlimited 与 Performance 50,000 个。一个定期比对记录数量和修改时间的作业,能抓住数据流漏掉的东西。
中间件还是直连
点对点是对的次数,比平台厂商愿意承认的要多。一个来源、一个目标、一个方向、适中的量、一份稳定的契约:直接建,省掉那份许可证。
中间件挣回它成本的时刻,是拓扑不再是一条线的时候。多个系统交换数据、业务人员需要不经部署就改动转换逻辑、需要跨若干各自独立出故障的系统做编排、确实需要集中的监控与重试。
说句老实话:中间件是把成本挪走,而不是消除。你仍然要为映射、错误处理和运维知识付钱,然后又加上一份许可证、第二条流水线,以及需要另外招人的第二套技能。API 配额并不会因此改变,因为中间件调用的就是你的代码原本要调用的那些 API。
选它是因为你的拓扑需要它,而不是因为它看起来能少写代码。我们的自建还是采购决策指南对底层系统讨论了同样的取舍,而CRM 与 ERP 集成指南覆盖了多系统的情形。如果你希望有人来评估而不是争论,那正是我们的软件开发服务开始的地方。
沙箱、部署与 API 版本
在沙箱里开发。不要对着生产,也不要对着一个不共享生产配置的 Developer Edition 组织,因为真正会弄坏你的正是配置。
要理解刷新做了什么。它用一份来自生产的新副本替换沙箱,所以只存在于沙箱里的测试数据会消失。任何必须活过刷新的东西,都得写成脚本并且可以重复运行。团队通常是丢掉一周的测试数据之后才学会这一点。
在每一条请求路径上显式固定你的 API 版本,并了解退役策略。Salesforce 的 API 生命周期终止策略承诺每个版本至少支持三年,并在支持结束前至少一年通知客户。版本 21.0 到 30.0 已在 Summer ‘25 退役,对已退役版本发起的请求会返回 410 Gone。
那是一个硬停止而不是性能下降,这正是版本固定属于你维护计划的原因。同样的纪律也适用于你自己对外发布的 API,我们在 API 版本管理一文中讨论过。
英国数据保护与 CRM 数据
CRM 几乎全部是个人数据:姓名、雇主、电话号码、电子邮件地址、关于对话的记录。把它在系统之间搬动,就是英国 GDPR 意义下的处理。
第一个问题是谁是控制者。英国信息专员办公室关于控制者与处理者的指引把控制者定义为决定处理目的和方式的一方,把处理者定义为代表控制者进行处理的一方。当一家代理商为你构建并运行集成时,那家代理商通常是处理者,而一份满足第 28 条要求的书面合同是强制的,不是可选的。
第二个问题是跨境传输。Salesforce 组织和任何中间件都可能位于英国境外,而信息专员办公室的国际传输指引列出了可用的机制以及何时需要做传输风险评估。在签字之前先确定数据会落在哪里。
由此得出三个后果。不要复制你并不需要的字段,因为最小化既是法律要求,也意味着更少的映射工作。不要在没有认真判断的情况下把生产环境的个人数据放进沙箱。还要确保删除会传播,因为一个在 Salesforce 里被抹掉、却在你的数据仓库里原封不动的联系人,就是一个活着的合规问题,而当 AI 智能体也能触达这些记录时同样如此。
Salesforce 集成的成本
Salesforce 在自己的定价页面上公布版本和许可证价格,我们在这里不引用任何数字,因为决定集成设计的是这些许可证产生的 API 配额,而不是标价。
下面的数字是 Mecanik 自己的英国专业服务估算,不是厂商定价,并且假设组织已经存在、也有一位能回答问题的管理员。
一个简单的单向集成,也就是网页表单创建一个带外部 ID 的 Lead 并配上合理的错误处理,通常是 GBP 3,000 到 GBP 7,000。一两个对象的双向同步,加上冲突解决和一个对账作业,一般是 GBP 15,000 到 GBP 40,000。一个基于 Pub/Sub、带重放、死信处理和监控的事件驱动集成,通常落在 GBP 30,000 到 GBP 80,000 之间。
交付物里应该有什么
一份与业务方达成一致而不是靠推断得来的字段级映射文档。每一个同步对象上的外部 ID。带死信存储和书面重新提交流程的错误处理。一个对账作业。针对组织配额的 API 消耗监控,并在远低于上限处告警。用于令牌轮换、证书到期和重放的操作手册。写成脚本、能活过刷新的沙箱配置。没有这些的集成,无论发票上怎么写,都是一个原型。
持续成本
为监控、每年三次的 Salesforce 版本更新、凭据轮换,以及管理员不打招呼就会做的字段改动,预留每月 GBP 400 到 GBP 1,500。愿意为这一项付钱的组织,就是那些集成一直能用的组织。
把它做出来
这里的失败模式一致得有点无聊:配额发现得太晚、一个没人审计过的触发器、一个本该是 Contact 的 Lead、没有办法重放一个失败的批次。这四件在设计阶段防起来都很便宜,等到真实记录已经存在再去修就很贵。
Mecanik 把构建和维护 Salesforce 集成作为软件开发工作的一部分,并且在写任何代码之前,先从审计该组织的配额、触发器和数据模型开始。如果你要的是一件范围明确的集成工作而不是一份完整的合作,也可以直接雇一位网页开发者。
常见问题
一个 Salesforce 集成每天能用多少次 API 调用? 这取决于版本和许可证数量,而且配额是组织级的,不是按集成分配的。带 API 访问权的 Enterprise 和 Professional 版本获得 100,000 次调用,外加每个 Salesforce 或 Salesforce Platform 许可证 1,000 次;Unlimited 和 Performance 获得 100,000 次,外加每个许可证 5,000 次;Developer Edition 在滚动的 24 小时内一律 15,000 次。
Salesforce 应该用 REST API 还是 Bulk API? 交互式、低流量、记录形状的工作用 REST API,量大且可以接受异步答案的加载与导出用 Bulk API 2.0。介于两者之间的情况,每次请求 200 条记录的 sObject Collections 和每次请求 25 个子请求的 Composite 对配额都只算一次调用,能消除大部分压力。
服务器到服务器的 Salesforce 集成该用哪种 OAuth 流程? 用 JWT 承载流程或客户端凭据流程,并以一个仅 API 的专用集成用户身份运行。用户名密码流程在较新的组织中默认被封锁,而且已排期退役,所以不应该用于新工作。另外要注意,从 Spring ‘26 起连接应用的创建受到限制,Salesforce 现在推荐外部客户端应用。
为什么我的 Salesforce 集成只在大批次时失败? 几乎总是因为某个没有做批量化的 Apex 触发器。Salesforce 交给触发器的是一组记录,而按每次只收到一条记录来写的触发器会对每条记录各跑一次查询,在你的批次到达时超出 100 条 SOQL 查询的限制。它对界面上一条一条保存记录的用户完全正常,所以才一直没被发现。
和 Salesforce 集成一定需要中间件吗? 单一来源、单一目标、单向且量适中的集成并不需要,直接构建更便宜也更简单。中间件挣回成本的时刻,是多个系统开始交换数据、业务人员需要不经部署就改映射,或者你需要集中编排与重试的时候。它是把成本挪走而不是消除,也不会增加你的 API 配额。
评论