Salesforce Connect:为架构师打造的实时数据集成终极指南

背景与应用场景

作为一名 Salesforce 架构师 (Salesforce Architect),我在设计企业级解决方案时,面临的核心挑战之一便是如何优雅地整合 Salesforce 与外部系统的数据。传统的做法通常依赖于 ETL (Extract, Transform, Load) 工具,通过批量或准实时的数据复制,将外部数据同步到 Salesforce 的自定义对象中。这种方式虽然成熟,但存在数据延迟、存储成本高、维护复杂等问题。在很多业务场景下,用户需要的仅仅是在 Salesforce 界面中“看一眼”外部系统的实时数据,而非拥有并存储它。

Salesforce Connect 正是为解决这一挑战而生的数据虚拟化 (Data Virtualization) 解决方案。它允许 Salesforce 以一种无缝的方式实时访问、显示和操作存储在外部系统中的数据,而无需将这些数据实际复制到 Salesforce 平台。这些外部数据在 Salesforce 中以外部对象 (External Objects) 的形式呈现,对于最终用户而言,其外观和行为与标准的 Salesforce 对象(如客户或机会)几乎没有区别。

典型的应用场景包括:

  • 订单管理:销售人员在客户 (Account) 页面上,需要查看该客户在企业资源规划 (ERP) 系统中的所有历史订单和发货状态。通过 Salesforce Connect,可以直接实时查询并展示 ERP 中的订单数据,而无需每晚同步数百万条订单记录。
  • - 旧系统数据访问:企业在迁移到 Salesforce 的过程中,可能暂时无法将所有历史数据从旧的本地 (On-premise) 系统中迁移出来。Salesforce Connect 可以提供一个过渡方案,让用户在 Salesforce 中继续访问这些旧数据,直至迁移完成。 - 统一客户视图 (360-Degree View):当客户数据分散在多个系统(如财务系统、支持门户、数据仓库)时,Salesforce Connect 可以将这些系统的数据作为外部对象引入,在客户记录页面上聚合展示,为用户提供一个完整的客户视图。 - 符合数据驻留法规:在某些行业或国家,特定的数据(如医疗记录或金融交易)必须存储在本地或指定的地理位置。Salesforce Connect 允许在 Salesforce 中“引用”这些数据,满足业务需求的同时,遵守了数据驻留的法规要求。

从架构层面看,Salesforce Connect 是一种低侵入性、高敏捷性的集成模式,它将 Salesforce 从一个纯粹的数据“容器”转变为一个强大的数据“聚合器”和“交互中心”。


原理说明

Salesforce Connect 的核心是“按需查询”,它在用户或自动化流程请求数据时,实时向外部系统发起一个 API 调用。这个过程对用户是透明的。其实现依赖于一套标准的适配器 (Adapters) 框架。

1. OData 适配器

Salesforce Connect 的主要连接方式是通过 OData (Open Data Protocol)。OData 是一个基于 HTTP 和 RESTful API 的 ISO/IEC 批准的标准,它定义了一套构建和消费可查询、可互操作 RESTful API 的最佳实践。简单来说,它就像是为数据源提供的 SQL 接口,但通过 Web API 实现。

  • OData 2.0 & 4.0:Salesforce Connect 支持 OData 2.0 和 4.0 版本。当您配置一个外部数据源 (External Data Source) 时,只需提供外部系统 OData 服务的根 URL。Salesforce 会自动发现该服务暴露的数据实体 (Entities),并允许您选择将哪些实体同步为 Salesforce 中的外部对象。
  • 查询转换:当用户通过列表视图、报表或 SOQL 查询一个外部对象时,Salesforce 平台会自动将这个请求转换为一个等效的 OData 查询(例如,带有 $filter, $select, $top 等参数的 HTTP GET 请求),并发送到外部系统的 OData 端点。外部系统执行查询后,将结果以 OData 格式返回,Salesforce 再将其解析并呈现给用户。

2. Apex 连接器框架 (Apex Connector Framework)

如果外部系统不提供 OData 接口怎么办?这就是 Apex 连接器框架 (Apex Connector Framework) 发挥作用的地方。它是一组 Apex 接口和类,允许开发人员使用 Apex 代码编写自定义适配器,从而连接到任何可以通过 Apex Callout 访问的 Web 服务(如 REST 或 SOAP API)。

架构师需要理解,这是一个更灵活但开发成本也更高的选项。开发人员需要实现 DataSource.ProviderDataSource.Connection 等接口,在其中编写代码来处理认证、查询、创建、更新和删除等操作的逻辑,将 Salesforce 的请求手动翻译成目标系统 API 的格式。

3. Salesforce 适配器 (Cross-Org)

Salesforce Connect 还提供了一个专门的适配器,用于连接另一个 Salesforce org。这在大型企业中非常有用,例如,一个集团公司下的多个子公司各自拥有独立的 Salesforce org,总部可以通过 Salesforce Connect 实时查看各子公司的关键数据(如销售管道),而无需进行复杂的 org 间数据同步。

4. 外部对象 (External Objects)

无论使用哪种适配器,外部数据在 Salesforce 中都表现为外部对象。它们有自己的 API 名称(以 __x 结尾),可以建立与标准或自定义对象的关系(查找、间接查找、外部查找),可以配置页面布局、字段级安全,并且可以在 Apex、Flow 和 API 中进行查询。但它们始终是外部数据的“代理”或“指针”,数据本身并不存储在 Salesforce 的数据库中。


示例代码

对于架构师来说,理解 Apex 连接器框架的结构至关重要,因为它揭示了 Salesforce Connect 的底层可扩展性。以下是一个简化的官方文档示例,展示了如何为自定义数据源实现 DataSource.Connection 类。这个类定义了如何连接到外部系统并执行数据操作。

Apex Connector Framework 示例 - Connection Class

假设我们要连接到一个虚构的简单 REST API,用于管理“订单”数据。下面的代码展示了如何处理查询操作。

/**
 * The DataSource.Connection class is responsible for managing the connection
 * to the external system and for handling data operations like query, search,
 * and DML (upsert, delete).
 */
public class SimpleOrderConnection extends DataSource.Connection {

    // A reference to the External Data Source definition in Salesforce Setup.
    private DataSource.ConnectionParams connectionInfo;

    /**
     * Constructor for the connection.
     * @param connectionParams Provides access to the External Data Source settings.
     */
    public SimpleOrderConnection(DataSource.ConnectionParams connectionParams) {
        this.connectionInfo = connectionParams;
    }

    /**
     * This method is called when a user or process executes a SOQL query
     * against the External Object.
     * @param queryContext Contains details of the SOQL query.
     * @return A list of rows, where each row is a map of column name to value.
     */
    override public DataSource.TableResult query(DataSource.QueryContext queryContext) {
        // Construct the URL for the external system's API endpoint.
        String endpoint = 'https://api.example.com/orders';
        
        // Build the request. In a real scenario, you would translate
        // queryContext.queryMoreInfo, queryContext.filters, etc., into
        // API-specific query parameters.
        HttpRequest req = new HttpRequest();
        req.setMethod('GET');
        req.setEndpoint(endpoint);
        // Best practice: Use Named Credentials for authentication.
        // req.setEndpoint('callout:My_Named_Credential/orders');

        Http http = new Http();
        HttpResponse res = http.send(req);

        List<Map<String, Object>> responseRows = new List<Map<String, Object>>();

        if (res.getStatusCode() == 200) {
            // Parse the JSON response from the external system.
            // The response is expected to be an array of order objects.
            List<Object> externalOrders = (List<Object>) JSON.deserializeUntyped(res.getBody());

            for (Object orderObj : externalOrders) {
                Map<String, Object> externalOrder = (Map<String, Object>) orderObj;
                Map<String, Object> row = new Map<String, Object>();
                
                // Map the external system's fields to the External Object's fields.
                // 'ExternalId' is a mandatory field for any external object.
                row.put('ExternalId', (String) externalOrder.get('id'));
                row.put('DisplayUrl', '/lightning/r/Order__x/' + (String) externalOrder.get('id') + '/view');
                row.put('OrderNumber__c', (String) externalOrder.get('orderNumber'));
                row.put('Status__c', (String) externalOrder.get('status'));
                row.put('TotalAmount__c', (Decimal) externalOrder.get('totalAmount'));
                
                responseRows.add(row);
            }
        } else {
            // Proper error handling is crucial.
            throw new DataSource.HandledException('Remote system returned an error: ' + res.getStatus());
        }

        // Return the data in the format Salesforce expects.
        return DataSource.TableResult.getTableResult(true, null, null, responseRows);
    }
}

注释说明:上述代码的核心是 query 方法。当 Salesforce 平台需要查询外部对象 Order__x 时,它会调用此方法。开发人员的职责是在此方法内部:

  1. 解析 DataSource.QueryContext 对象,以理解查询的条件(如 WHERE 子句、LIMIT 等)。
  2. 构建一个对外部系统 API 的 HTTP 请求。
  3. 发送请求并接收响应。
  4. 将响应(通常是 JSON 或 XML)解析成一个 List<Map<String, Object>> 结构,其中每个 Map 代表一行数据。
  5. 将这个结构封装在 DataSource.TableResult 对象中返回给 Salesforce 平台。

从架构角度看,这个自定义连接器是外部系统与 Salesforce 之间的“翻译层”和“协议转换器”。


注意事项

作为架构师,在推荐或设计 Salesforce Connect 解决方案时,必须充分考虑其局限性和潜在风险。

1. 性能和延迟

最重要的一点:每次访问外部对象数据都会触发一个实时的 API Callout。这意味着用户体验直接受到外部系统的响应速度和网络延迟的影响。一个响应缓慢的外部 API 会导致 Salesforce 页面加载缓慢,甚至超时。因此,Salesforce Connect 不适用于需要低延迟、高吞吐量数据访问的场景。

2. API 限制 (Governor Limits)

Salesforce Connect 的调用计入 Salesforce 的 API Callout 限制。此外,外部系统本身通常也有 API 调用频率限制(Rate Limiting)。在高频访问的场景下(例如,大量用户同时访问包含外部对象的页面,或批处理作业查询外部对象),很容易耗尽任一方的 API 限额。必须对预期的负载进行评估。

3. SOQL 和报表功能的限制

外部对象在查询和分析方面功能受限:

  • 不支持聚合查询,如 COUNT()SUM()。所有聚合计算都需要在客户端或通过其他方式完成。
  • 在报表中,外部对象不能作为主对象(除非是特定类型的报表)。通常它们只能通过关系被包含在报表中。
  • 排序、筛选等操作的能力取决于外部数据源是否支持这些操作并将其暴露给 OData 或自定义连接器。

4. 数据修改和写入能力

默认情况下,外部对象是只读的。要使其可写 (Creatable, Updatable, Deletable),外部数据源必须满足特定条件。对于 OData,服务必须正确实现并支持相应的 HTTP 方法(POST, PATCH, DELETE)。对于 Apex 自定义连接器,则需要实现 DataSource.Updatable 接口并编写相应的 DML 操作代码。启用可写外部对象会增加集成的复杂性和风险。

5. 身份验证和安全性

与外部系统的连接安全至关重要。最佳实践是使用命名凭据 (Named Credentials)。它将端点 URL 和身份验证信息(如用户名密码、OAuth 2.0 令牌)分离开来,由 Salesforce 平台负责管理认证过程。这避免了在代码或配置中硬编码敏感信息,并简化了证书管理。

6. 成本

Salesforce Connect 是一个付费的附加产品。在方案设计时,必须考虑其许可成本,并权衡其与传统 ETL 方案的总体拥有成本 (TCO)。


总结与最佳实践

Salesforce Connect 是一个强大的、战略性的集成工具,它完美诠释了“数据虚拟化”的架构思想。它并非要取代所有传统的 ETL 集成,而是为特定的业务场景提供了一个更敏捷、更实时的选择。

作为 Salesforce 架构师,我的核心建议如下:

  • 明确用例:优先将 Salesforce Connect 用于“实时查看、少量操作”的场景。当用户需要在上下文中(如在客户记录旁)查看最新的外部数据时,它是理想选择。
  • - 避免用于批量处理和分析:对于需要进行大量数据处理、复杂聚合或深度分析的场景,传统的 ETL 或数据仓库方案仍然是更合适的选择。不要使用 Salesforce Connect 来运行需要处理数万条记录的批处理作业。 - 性能优先:在设计阶段就必须与外部系统的所有者合作,确保其 API 性能满足业务对 Salesforce 页面加载时间的预期。进行充分的负载测试。 - 选择正确的适配器:如果外部系统提供标准的、性能良好的 OData v4 服务,优先使用 OData 适配器,因为这是最快、最简单的实现方式。只有在无法提供 OData 接口时,才考虑投入资源开发 Apex 自定义连接器。 - 治理与监控:建立对外部 API 调用频率和响应时间的监控机制。使用 Salesforce 事件监控 (Event Monitoring) 来跟踪对外部对象的查询性能和错误率,以便在问题发生时能快速定位。

总之,Salesforce Connect 是一种架构上的“巧”劲,它通过引用而非复制,巧妙地解决了许多跨系统数据可见性的难题。正确地使用它,可以极大地提升用户体验、降低开发和维护成本,并构建一个更加灵活和互联的企业应用生态系统。

评论

此博客中的热门博文

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

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

Salesforce Data Loader 全方位指南:数据迁移与管理的最佳实践