Salesforce Connect:无缝集成外部数据的实时桥梁
身份:Salesforce 咨询顾问
背景与应用场景
在当今的企业数字化转型浪潮中,数据已经成为驱动业务决策的核心资产。然而,一个普遍存在的挑战是数据孤岛(Data Silos)问题。企业的关键数据往往分散在不同的系统中,例如:客户的订单历史存储在企业资源规划(ERP)系统中,产品库存信息在供应链管理(SCM)系统中,而客户关系管理则由 Salesforce 负责。当销售人员在 Salesforce 中查看客户信息时,如果无法实时获取其在 ERP 系统中的订单和支付状态,就很难提供全面、及时的客户服务。
传统的解决方案通常是采用 ETL(Extract, Transform, Load)工具,定期将外部数据抽取、转换并加载到 Salesforce 中。这种方式虽然可行,但存在几个明显的缺点:
- 数据延迟:数据不是实时的,可能导致业务决策基于过时的信息。
- 存储成本:将大量外部数据复制到 Salesforce 会消耗宝贵的数据存储空间,增加运营成本。
- 维护复杂性:需要维护复杂的同步逻辑、监控任务和错误处理机制,增加了 IT 部门的负担。
为了解决这些痛点,Salesforce 推出了 Salesforce Connect,它是一种强大的数据集成服务。Salesforce Connect 遵循数据虚拟化(Data Virtualization)的理念,允许您在 Salesforce 中直接查看、搜索和修改存储在外部系统中的数据,而无需将这些数据实际复制到 Salesforce 中。这些外部数据在 Salesforce 中以 External Objects (外部对象) 的形式呈现,对于用户来说,其使用体验与标准的 Salesforce 自定义对象几乎没有区别。
以下是一些典型的应用场景:
- 360度客户视图:在客户(Account)页面上,直接展示来自 ERP 系统的历史订单、发货状态和发票信息。
- 实时库存查询:销售人员在创建报价(Quote)或机会(Opportunity)时,能够实时查询外部库存系统,确保产品可用性。
- 金融数据整合:在金融服务云(Financial Services Cloud)中,将客户的银行账户、交易记录等核心银行系统数据作为外部对象进行展示。
- 法规遵从:对于某些有严格数据驻留(Data Residency)要求的行业(如医疗、政府),可以将敏感数据保留在本地或指定的系统中,同时通过 Salesforce Connect 在 Salesforce UI 中进行安全的访问和操作。
作为一名 Salesforce 咨询顾问,我经常向客户推荐 Salesforce Connect,因为它提供了一种轻量级、低成本且实时的数据集成方案,能够快速打破数据壁垒,提升用户体验和业务效率。
原理说明
Salesforce Connect 的核心原理是“按需访问,而非复制存储”。当用户在 Salesforce 中执行访问外部对象的操作时(例如,打开记录、查看列表视图、运行报表),Salesforce 会在后台实时向外部数据源发起一个 API 调用(Callout)。外部系统接收到请求后,处理并返回相应的数据,Salesforce 再将这些数据呈现给用户。整个过程对用户是透明的。
实现这一机制的关键在于两个核心组件:External Data Sources (外部数据源) 和 External Objects (外部对象)。
1. 外部数据源 (External Data Sources)
外部数据源是 Salesforce 与外部系统之间的连接配置。它定义了如何连接到外部系统、使用何种协议进行通信以及采用哪种身份验证方式。Salesforce Connect 支持多种适配器(Adapters)来连接不同类型的外部系统:
- OData 2.0/4.0 Adapter:OData (Open Data Protocol) 是一种基于 RESTful API 的开放标准,用于构建和消费可查询、可操作的 Web 服务。如果您的外部系统(如 SAP、SharePoint)提供了 OData 端点(Endpoint),这是最常用、最简单的连接方式。
- Cross-Org Adapter:用于连接另一个 Salesforce org。您可以将一个 org 中的数据作为外部对象实时展示在另一个 org 中,非常适合公司内部多 org 架构的场景。
- Custom Adapter (Apex Connector Framework):如果您的外部系统不提供 OData 接口,但有自己的 REST 或 SOAP API,您可以使用 Apex Connector Framework 编写自定义的 Apex 代码来“翻译”Salesforce 的请求,并处理外部系统的响应。这提供了极高的灵活性,可以连接到几乎任何类型的外部数据源。
2. 外部对象 (External Objects)
在配置好外部数据源后,您可以“同步”该数据源。Salesforce 会查询外部系统的元数据(例如,OData 服务中的实体),并允许您选择要创建为外部对象的表或实体。创建后,外部对象就出现在 Salesforce 的设置菜单中,拥有自己的 API 名称(以 `__x` 结尾)。
您可以像操作自定义对象一样对外部对象进行配置:
- 设置字段级别的安全性和简档权限。
- 创建自定义选项卡和页面布局。
- 与其他 Salesforce 对象(标准或自定义)建立关系(查找关系、间接查找关系、外部查找关系)。
- 在 SOQL 查询、Salesforce 全局搜索、报表和仪表板中使用它们(存在一些限制)。
当用户与外部对象交互时,Salesforce Connect 会将用户的操作转换为相应的协议请求。例如,一个 SOQL 查询会被转换为一个 OData 查询(包含 `$filter`、`$select` 等参数),然后发送到外部数据源的 URL 端点。
示例代码
虽然 Salesforce Connect 的 OData 适配器大部分是声明式配置,但当我们面对没有标准 OData 接口的专有系统时,Apex Connector Framework 就显得至关重要。作为咨询顾问,为客户设计和实现这种自定义连接器是高级集成的常见需求。以下代码示例展示了如何创建一个简单的自定义适配器,它连接到一个虚构的外部数据服务。
此示例包含两个关键的 Apex 类:`DataSource.Provider` 和 `DataSource.Connection`。Provider 类负责声明连接器的能力和获取连接实例,而 Connection 类则负责处理实际的数据操作,如同步、查询和身份验证。
注意:以下代码严格遵循 Salesforce 官方文档中的 `DataSource` 命名空间和类结构。
创建自定义连接器 Provider 类
/** * MyCustomDataSourceProvider.cls * * Provider 类用于定义自定义连接器的元数据和功能。 * 它告诉 Salesforce 这个连接器支持哪些认证方式,以及需要哪些功能。 */ public class MyCustomDataSourceProvider extends DataSource.Provider { /** * getAuthenticationCapabilities() 方法 * 返回此连接器支持的认证类型列表。 * 这里我们声明它支持“基本认证”(用户名/密码)。 * @return 返回认证能力列表。 */ public override List<DataSource.AuthenticationCapability> getAuthenticationCapabilities() { List<DataSource.AuthenticationCapability> capabilities = new List<DataSource.AuthenticationCapability>(); capabilities.add(DataSource.AuthenticationCapability.BASIC); // 支持基本认证 return capabilities; } /** * getCapabilities() 方法 * 返回此连接器支持的操作类型。 * 例如,ROW_QUERY 表示支持行查询,SEARCH 表示支持搜索。 * @return 返回连接器能力列表。 */ public override List<DataSource.Capability> getCapabilities() { List<DataSource.Capability> capabilities = new List<DataSource.Capability>(); capabilities.add(DataSource.Capability.ROW_QUERY); // 支持基于行的查询 capabilities.add(DataSource.Capability.SEARCH); // 支持搜索功能 return capabilities; } /** * getConnection() 方法 * Salesforce 在需要与外部系统交互时会调用此方法。 * 它返回一个 DataSource.Connection 类的实例,该实例将处理实际的数据请求。 * @param connectionInfo 包含外部数据源配置信息的上下文。 * @return 返回 DataSource.Connection 的一个实例。 */ public override DataSource.Connection getConnection(DataSource.ConnectionParams connectionInfo) { return new MyCustomDataSourceConnection(connectionInfo); } }
创建自定义连接器 Connection 类
/** * MyCustomDataSourceConnection.cls * * Connection 类是自定义连接器的核心,负责处理所有与外部系统的通信。 * 它实现了同步(sync)、查询(query)和搜索(search)等核心逻辑。 */ public class MyCustomDataSourceConnection extends DataSource.Connection { private DataSource.ConnectionParams connectionInfo; /** * 构造函数 * @param connectionInfo 包含外部数据源配置,如端点URL、凭据等。 */ public MyCustomDataSourceConnection(DataSource.ConnectionParams connectionInfo) { this.connectionInfo = connectionInfo; } /** * sync() 方法 * 当管理员在 Salesforce 设置中点击“验证和同步”时调用此方法。 * 它应该连接到外部系统,获取其数据结构(表和列), * 并将其转换为 Salesforce 能理解的 DataSource.Table 和 DataSource.Column 对象。 * @return 返回可用于创建外部对象的表列表。 */ public override List<DataSource.Table> sync() { // 在实际项目中,这里会发起一个 HTTP Callout 到外部系统的元数据端点 // 以下为硬编码的示例,模拟从外部系统获取到的表结构 List<DataSource.Table> tables = new List<DataSource.Table>(); // 定义“订单”表的列 List<DataSource.Column> columns = new List<DataSource.Column>(); columns.add(DataSource.Column.text('OrderID', 255)); // 订单ID,文本类型 columns.add(DataSource.Column.text('CustomerName', 255)); // 客户名称 columns.add(DataSource.Column.url('DisplayUrl')); // Salesforce 要求的标准外部对象字段 columns.add(DataSource.Column.text('ExternalId')); // 外部ID,用于唯一标识记录 // 创建“订单”表 String tableName = 'Orders'; String tableLabel = 'Orders'; tables.add(DataSource.Table.get(tableName, tableLabel, null, columns)); return tables; } /** * query() 方法 * 当用户查询外部对象时(如打开列表视图或运行报表),此方法被调用。 * 它接收一个 DataSource.QueryContext 对象,其中包含查询的详细信息 * (如要查询的表、列、过滤条件、排序规则等)。 * @param context 查询上下文。 * @return 返回查询结果。 */ public override DataSource.TableResult query(DataSource.QueryContext context) { // 在实际项目中,这里会构建一个 HTTP 请求(例如 REST GET 请求), // 将 context 中的过滤条件转换为外部系统API的查询参数。 // 然后解析返回的 JSON/XML,并将其映射到 DataSource.Row 对象中。 // 以下为硬编码的示例,模拟返回的查询结果 List<Map<String, Object>> data = new List<Map<String, Object>>(); Map<String, Object> row1 = new Map<String, Object>(); row1.put('OrderID', 'ORD-001'); row1.put('CustomerName', 'Global Tech Inc.'); row1.put('ExternalId', 'ext-001'); row1.put('DisplayUrl', '/services/apexrest/myorg/orders/ext-001'); data.add(row1); Map<String, Object> row2 = new Map<String, Object>(); row2.put('OrderID', 'ORD-002'); row2.put('CustomerName', 'United Solutions'); row2.put('ExternalId', 'ext-002'); row2.put('DisplayUrl', '/services/apexrest/myorg/orders/ext-002'); data.add(row2); return DataSource.TableResult.get(context, data); } /** * search() 方法 * 当用户使用全局搜索时,此方法被调用。 * 逻辑与 query() 类似,但通常是为更广泛的文本搜索而优化。 * @param context 搜索上下文。 * @return 返回搜索结果列表。 */ public override List<DataSource.TableResult> search(DataSource.SearchContext context) { // 实现搜索逻辑,类似于 query() // 实际项目中,这会调用外部系统的搜索API return new List<DataSource.TableResult>(); } }
注意事项
在规划和实施 Salesforce Connect 项目时,必须充分考虑其限制和潜在影响,以确保方案的可行性和稳定性。
- API 调用限制:每次对外部对象的操作(查看记录、刷新列表、执行查询)都会消耗一个 Salesforce API Callout。请密切关注您的 org 的每日 Callout 限制。高频访问的外部对象可能会迅速耗尽这些限制,影响其他集成。
- 性能和延迟:由于数据是实时查询的,性能直接取决于外部数据源的响应速度和网络延迟。一个响应缓慢的外部系统会导致 Salesforce 页面加载缓慢,用户体验差。在实施前,必须对外部系统的 API 进行充分的性能测试。
- 外部对象功能限制:外部对象并不支持标准或自定义对象的所有功能。例如:
- 不支持 Apex Triggers、验证规则和工作流规则(部分功能可通过 Flow 实现)。
- 不支持将外部对象作为父项的主从关系。
- 在公式字段、报表和 SOQL 查询中的使用受到限制。例如,聚合查询(`COUNT()`、`SUM()`)的支持有限,并且外部对象不能是某些复杂报表类型的主对象。
- 记录所有权和共享模型与 Salesforce 标准对象不同,其访问权限主要由外部数据源的配置决定。
- 数据可写性:Salesforce Connect 是否支持对外部数据进行创建、编辑和删除操作,完全取决于外部数据源的设置。如果 OData 端点或自定义适配器实现了写操作,您可以在 Salesforce 中启用这些功能。否则,外部对象将是只读的。
- 身份验证:需要仔细规划身份验证策略。是使用一个共享的系统账户(Named Principal)连接外部系统,还是让每个用户使用自己的凭据(Per User)?这涉及到安全性和数据可见性的重要决策。 - 错误处理:必须设计健全的错误处理机制。如果外部系统宕机或返回错误,Salesforce 界面应能优雅地处理这些异常,并向用户提供清晰的提示。
总结与最佳实践
Salesforce Connect 是一个强大的数据集成工具,它通过数据虚拟化的方式,提供了一种“零拷贝”、实时的外部数据访问方案。它特别适用于那些数据量大、更新频繁,或者因合规性要求不能存储在 Salesforce 中的场景。
作为一名 Salesforce 咨询顾问,我为客户提供以下最佳实践建议:
- 明确业务需求,选择正确的工具:在选择 Salesforce Connect 之前,要先问一个关键问题:“我需要对这些数据在 Salesforce 中做什么?”如果只是查看和简单更新,Connect 是绝佳选择。如果需要复杂的自动化逻辑(如 Apex Triggers)、精细的共享模型或高性能的聚合报告,那么传统的 ETL 数据同步方案可能更合适。
- 优先使用标准适配器:如果外部系统支持 OData,请优先使用 OData 2.0 或 OData 4.0 适配器。这能最大限度地减少开发和维护成本。只有在无法使用标准适配器时,才考虑投入资源开发自定义的 Apex 连接器。
- 设计以性能为先:在设计页面布局和列表视图时,尽量减少默认加载的外部对象字段数量,避免一次性触发过多的数据请求。使用分页(Server-driven Paging)来处理大型数据集,而不是一次性加载所有记录。
- 理解并监控限制:在项目上线前,评估预期的使用量是否会超出 API Callout 限制。上线后,使用 Salesforce 的事件监控(Event Monitoring)或相关工具持续跟踪 Callout 的使用情况,以便及时优化。
- 建立清晰的治理模型:明确外部数据的所有权和维护责任。确保外部系统的 API 变更能够及时通知 Salesforce 团队,避免因外部接口变动导致集成中断。
总而言之,Salesforce Connect 并非万能的数据集成解决方案,但它在正确的场景下能够发挥巨大价值,帮助企业快速、高效地构建统一的客户视图,打破信息孤岛,从而做出更明智的业务决策。
评论
发表评论