精通 Salesforce Connect:通过外部对象实现实时数据集成

背景与应用场景

作为一名 Salesforce 架构师 (Salesforce Architect),我在设计企业级解决方案时,面临的核心挑战之一便是如何优雅地处理“数据孤岛”问题。企业的数据通常分散在多个异构系统中,例如后端的 ERP 系统(如 SAP、Oracle EBS)、本地数据库、专有的遗留系统或是其他云服务。传统的数据集成方式,如 ETL (Extract, Transform, Load),虽然强大,但其核心思想是“数据复制”。这意味着需要定期将外部数据抽取、转换并加载到 Salesforce 中,这带来了几个固有的问题:

  • 数据延迟:复制的数据永远不是 100% 实时的,存在同步窗口期,对于需要即时信息的业务场景(如查看实时订单状态、库存水平)是致命的。
  • 存储成本:将大量外部数据存储在 Salesforce 会消耗宝贵的数据存储空间,增加运营成本。
  • 数据治理与合规风险:数据的多次复制增加了数据管理的复杂性,尤其是在处理敏感数据(如 PII、PHI)时,可能会违反 GDPR、CCPA 等数据隐私法规。

Salesforce Connect 正是为了解决这些挑战而设计的。它是一种强大的数据虚拟化 (Data Virtualization) 解决方案。其核心理念并非“移动数据”,而是“按需访问数据”。通过 Salesforce Connect,外部系统中的数据可以作为外部对象 (External Objects) 无缝地呈现在 Salesforce UI 中,用户可以像操作标准或自定义对象一样查看、搜索甚至修改这些数据,而数据本身始终保留在源系统中。

典型的应用场景包括:

  1. 360度客户视图增强:在客户(Account)页面上,直接展示来自 ERP 系统的实时订单历史、发票信息和付款状态,让销售和客服人员无需切换系统即可获得完整视图。
  2. 大型产品目录集成:对于拥有数百万 SKU 的电商或制造业公司,将整个产品目录同步到 Salesforce 并不现实。通过 Salesforce Connect,可以实时查询外部产品信息管理 (PIM) 系统,展示产品详情。
  3. 敏感数据访问:当公司政策或法规要求某些财务或医疗数据必须保留在本地(on-premise)防火墙内时,可以使用 Salesforce Connect 在 Salesforce 中进行只读访问,满足业务需求的同时确保合规性。
  4. 多组织(Multi-Org)数据整合:对于拥有多个 Salesforce 组织的大型企业,可以使用 Salesforce Connect 的 Cross-Org 适配器,在一个组织中查看和操作另一个组织的数据,简化跨业务部门的协作。

原理说明

Salesforce Connect 的工作原理建立在“适配器”模型之上。当用户在 Salesforce 中执行一个针对外部对象的操作时(例如,查看列表视图、打开记录详情页),Salesforce 平台会通过一个名为外部数据源 (External Data Source) 的配置,将这个请求实时地转换成对外部系统的 API 调用。

整个流程可以分解为以下几个步骤:

  1. 用户请求:用户在 Salesforce 中与外部对象交互(例如,执行 SOQL 查询、点击记录链接)。
  2. 平台转换:Salesforce 平台拦截该请求,识别出它指向一个外部对象。
  3. 适配器调用:Salesforce Connect 框架根据外部数据源的配置,选择相应的适配器,并将 Salesforce 的请求(如 SOQL)转换为外部系统能够理解的查询语言(如 OData URL)。
  4. 外部通信:适配器通过网络向外部系统端点(Endpoint)发送请求。身份验证信息(通过命名凭证 Named Credential 管理)会包含在请求中,确保安全连接。
  5. 外部系统响应:外部系统处理请求,并返回数据(通常是 JSON 或 XML 格式)。
  6. 数据呈现:Salesforce Connect 接收到响应后,将其解析并实时呈现在 Salesforce UI 中,对最终用户而言,这个过程是透明的。

Salesforce Connect 主要提供以下几种类型的适配器:

  • OData 2.0 / 4.0 Adapter:这是最常用的适配器。OData (Open Data Protocol) 是一个基于 REST 的开放标准,用于构建和消费可查询、可互操作的 Web API。如果你的外部系统(如 SAP NetWeaver, Microsoft Dynamics)暴露了 OData 端点,集成工作会变得非常简单,只需通过点击式配置即可完成。
  • Cross-Org Adapter:专门用于连接另一个 Salesforce 组织。它利用 Salesforce REST API,可以轻松地将一个组织中的数据虚拟化到另一个组织中。
  • Salesforce Platform Adapter (原名 Lightning Platform Adapter): 允许您连接到同一个 Salesforce 组织中的其他数据,或通过 GraphQL API 连接到 Salesforce 的其他服务。
  • Custom Adapter (Apex Connector Framework):当外部系统不提供 OData 接口,但拥有自己的 REST 或 SOAP API 时,这就是终极解决方案。开发人员可以利用 Apex 编写自定义适配器,通过实现 `DataSource.Provider` 和 `DataSource.Connection` 接口,教会 Salesforce 如何与任何外部系统进行通信。这为 Salesforce Connect 提供了无限的扩展性。

示例代码

对于架构师来说,理解自定义适配器的能力至关重要,因为它解锁了与任何 API 端点的连接。以下是一个基于 Salesforce 官方文档的 Apex Connector Framework 示例,它演示了如何创建一个简单的自定义连接器。假设我们要连接到一个返回简单数据的外部 Web 服务。

该框架主要包含两个核心类:`DataSource.Provider` 用于定义外部数据源的元数据和身份验证,而 `DataSource.Connection` 则负责处理实际的数据操作,如查询和同步。

1. 实现 DataSource.Provider

这个类声明了连接器的能力,比如它支持哪种身份验证方式。

/**
 * The DataSource.Provider class is used to declare the capabilities
 * and authentication settings for a custom adapter.
 */
global class SimpleProvider extends DataSource.Provider {
    /**
     * Declares the authentication capabilities.
     * This connector supports basic authentication (username/password).
     */
    override global List<DataSource.AuthenticationCapability> getAuthenticationCapabilities() {
        List<DataSource.AuthenticationCapability> capabilities =
            new List<DataSource.AuthenticationCapability>();
        capabilities.add(DataSource.AuthenticationCapability.BASIC);
        return capabilities;
    }

    /**
     * Declares the general capabilities of the connector.
     * ROW_QUERY indicates that it can fetch individual rows or lists of rows.
     */
    override global List<DataSource.Capability> getCapabilities() {
        List<DataSource.Capability> capabilities =
            new List<DataSource.Capability>();
        capabilities.add(DataSource.Capability.ROW_QUERY);
        return capabilities;
    }

    /**
     * Returns an instance of the connection class.
     * This is called by the framework to get the object that will handle data operations.
     */
    override global DataSource.Connection getConnection(DataSource.ConnectionParams connectionParams) {
        return new SimpleConnection(connectionParams);
    }
}

2. 实现 DataSource.Connection

这个类是数据操作的核心,它实现了查询、同步等逻辑。

/**
 * The DataSource.Connection class handles the actual data retrieval
 * and metadata discovery (sync) for the external system.
 */
global class SimpleConnection extends DataSource.Connection {
    private DataSource.ConnectionParams connectionInfo;

    /**
     * Constructor that receives connection parameters.
     */
    global SimpleConnection(DataSource.ConnectionParams connectionParams) {
        this.connectionInfo = connectionParams;
    }

    /**
     * The sync method is called when an administrator clicks "Validate and Sync"
     * on the External Data Source definition. It should return a list of tables (External Objects).
     */
    override global List<DataSource.Table> sync() {
        // In a real implementation, you would make an API callout to the external
        // system to get the list of available tables and their schemas.
        // For this example, we are hardcoding one table definition.

        List<DataSource.Column> columns = new List<DataSource.Column>();
        columns.add(DataSource.Column.text('ID', 255));
        columns.add(DataSource.Column.text('Name', 255));
        columns.add(DataSource.Column.url('Url'));
        // The 'DisplayUrl' is a special column name for the standard external ID field.
        columns.add(DataSource.Column.text('DisplayUrl', 255)); 

        // Define a table named 'Simple'
        return new List<DataSource.Table>{
            DataSource.Table.create('Simple', columns)
        };
    }

    /**
     * The query method is executed when Salesforce needs to fetch data
     * from the external system (e.g., via a SOQL query or viewing a list view).
     */
    override global DataSource.TableResult query(DataSource.QueryContext context) {
        // In a real-world scenario, you would build an HTTP request based on the
        // QueryContext, which contains details like filters (WHERE clause) and
        // columns to select.
        // For simplicity, this example returns static data.
        
        List<Map<String, Object>> data = new List<Map<String, Object>>();
        
        Map<String, Object> row1 = new Map<String, Object>();
        row1.put('ID', '100');
        row1.put('Name', 'Sample Record 1');
        row1.put('Url', 'http://www.salesforce.com');
        row1.put('DisplayUrl', '100'); // This value must match the external ID.
        data.add(row1);

        Map<String, Object> row2 = new Map<String, Object>();
        row2.put('ID', '101');
        row2.put('Name', 'Sample Record 2');
        row2.put('Url', 'http://developer.salesforce.com');
        row2.put('DisplayUrl', '101'); // This value must match the external ID.
        data.add(row2);

        return DataSource.TableResult.success(context.tableSelection, data);
    }
}

⚠️ 以上代码是基于 Salesforce 官方文档中 Apex Connector Framework 的标准实现模式。编写自定义适配器需要深入理解 Apex Callout 机制以及外部系统 API 的工作方式。


注意事项

作为架构师,在推荐使用 Salesforce Connect 之前,必须充分评估其局限性,并向业务方和开发团队明确这些权衡。这对于管理期望和避免项目失败至关重要。

  • 性能与延迟:每一次对外部对象的数据访问都会触发一次实时的 API Callout。这意味着用户操作的响应时间直接取决于外部系统的响应速度和网络延迟。对于需要高性能、低延迟的场景,Salesforce Connect 可能不是最佳选择。
  • API 调用限制:这些 Callout 会消耗 Salesforce 的 API 调用限制,同时也会受到外部系统自身的 API 速率限制。在高并发或高数据量的场景下,很容易达到限制瓶颈,导致服务中断。必须进行严格的容量规划。
  • 数据可写性:默认情况下,外部对象是只读的。要启用编辑、创建和删除功能,外部数据源必须启用“可写外部对象”选项,并且外部系统本身必须支持这些写操作的 API。
  • SOQL 查询限制:针对外部对象的 SOQL 查询功能有限。例如,不支持聚合函数(`COUNT()`、`SUM()`等),不支持复杂的`JOIN`,`ORDER BY`子句的行为也可能与标准对象不同。这限制了其在复杂报表和分析中的应用。
  • 不支持的功能:外部对象不支持许多标准 Salesforce 功能,例如:公式字段(跨对象公式通常不支持)、验证规则、Apex Triggers(可以使用 `Apex transactions for Salesforce Connect`,但有限制)、记录类型、队列以及标准报表和仪表盘(尽管可以通过 Analytics Studio for Tableau CRM (原 Einstein Analytics) 进行分析)。
  • 搜索行为:外部对象可以被包含在全局搜索中,但其搜索机制与标准对象不同。Salesforce 不会为外部数据建立索引,而是将搜索请求实时传递给外部系统。因此,搜索性能和结果的准确性完全依赖于外部系统的搜索能力。
  • 身份验证:必须使用命名凭证 (Named Credentials) 来管理外部系统的身份验证信息。这是安全和可维护性的最佳实践,避免了在代码或配置中硬编码凭据。

总结与最佳实践

Salesforce Connect 是一个出色的、具有战略意义的集成工具,但它不是万能的。它是一种“手术刀”,而非“瑞士军刀”,应在合适的场景下精准使用。

总结:

Salesforce Connect 的核心价值在于实时、无复制的数据访问。它解决了数据延迟、存储成本和部分合规性问题,为用户提供了统一的、无缝的数据体验。它通过适配器模型连接到外部系统,将外部数据表虚拟化为 Salesforce 中的外部对象。

架构师的最佳实践:

  1. 明确集成模式:在项目初期,就要明确选择哪种集成模式。
    • 选择 Salesforce Connect:当业务需要少量、实时的外部数据,数据更新频繁,且数据所有权和存储位置有严格要求时。例如,“查看当前订单状态”。
    • 选择 ETL/数据复制:当需要对大量数据进行复杂分析、报表、或需要高性能批量处理时。例如,“分析过去五年的销售趋势”。
  2. 优先使用标准适配器:如果外部系统支持 OData,应始终优先使用 OData 适配器。这能最大限度地减少开发和维护成本。
  3. 谨慎设计外部对象:不要试图将一个复杂的外部数据模型原封不动地搬到 Salesforce。只暴露业务流程中真正需要的字段,以减少数据传输量,优化性能。
  4. 管理 Callout 行为:在页面布局、列表视图和查询中,要非常小心。一个包含多个外部对象字段的页面布局可能会在加载时触发多次 Callout。应教育用户和开发人员编写带有 `WHERE` 子句的精确查询,避免全表扫描。
  5. 进行充分的性能测试:在上线前,必须在模拟真实负载的环境下对 Salesforce Connect 的性能进行压力测试,以确保外部系统和网络能够承受预期的并发访问量。
  6. 强大的治理模型:建立对 API 限制的监控和警报机制,无论是 Salesforce 侧还是外部系统侧,都要有清晰的治理策略,以防系统滥用导致服务中断。

通过遵循这些原则,Salesforce 架构师可以充分利用 Salesforce Connect 的强大功能,构建出既灵活又高效的集成解决方案,真正打破企业内部的数据壁垒。

评论

此博客中的热门博文

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

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

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