微调 SQL 并解决 AD FS 的延迟问题

AD FS 2016 的更新中,我们引入了以下改进,以降低跨数据库的延迟。 即将发布的 AD FS 2019 更新将包括这些改进。

后台线程中的内存中缓存更新

在以前的 Always on 可用性 (AoA) 部署中,任何“读取”操作都会出现延迟,因为主节点可能位于独立的数据中心。 两个不同数据中心之间的调用导致延迟。

AD FS 的最新更新中添加了一个用于刷新 AD FS 配置缓存的后台线程以及一个用于设置刷新时间段的设置,因而降低了延迟。 由于数据库缓存更新已移至后台线程,因此请求线程中花费在数据库查找上的时间大幅减少。

backgroundCacheRefreshEnabled 设置为 true 时,AD FS 将启用后台线程来运行缓存更新。 通过设置 cacheRefreshIntervalSecs,可以将从缓存提取数据的频率自定义为某个时间值。 当 backgroundCacheRefreshEnabled 设置为 true 时,默认值将设置为 300 秒。 在设置的持续时间值过后,AD FS 将开始刷新其缓存,并且在进行更新的同时,将继续使用旧缓存数据。

当 AD FS 收到某个应用程序的请求时,AD FS 将从 SQL 检索该应用程序并将其添加到缓存中。 在 cacheRefreshIntervalSecs 值处,使用后台线程刷新缓存中的应用程序。 当缓存中存在某个条目时,传入的请求将在进行后台刷新的同时使用缓存。 如果有 5 * cacheRefreshIntervalSecs 的时间未访问某个条目,则会从缓存中删除该条目。 一旦达到可配置的 maxRelyingPartyEntries 值,也可以从缓存中删除最旧的条目。

注意

如果 AD FS 收到来自 SQL 的通知,其中指出数据库中发生了更改,则不会根据 cacheRefreshIntervalSecs 值刷新缓存的数据。 此通知将触发缓存刷新。

有关设置缓存刷新的建议

默认的缓存刷新值为 5 分钟。 建议将其设置为 1 小时,以减少 AD FS 不必要地刷新数据,因为在发生任何 SQL 更改的情况下,都会刷新缓存数据。

AD FS 为 SQL 更改注册一个回调,在发生更改时,AD FS 将收到通知。 通过此方法,AD FS 可以在 SQL 发生每项新的更改时立即接收更改。

如果出现网络小故障,导致 AD FS 错过 SQL 通知,AD FS 将按照缓存刷新值指定的间隔进行刷新。 如果怀疑 AD FS 和 SQL 之间存在任何连接问题,建议将缓存刷新值设置为小于 1 小时。

配置说明

配置文件支持多个缓存条目。 可以根据组织的需要配置下面列出的所有设置。

以下示例启用后台缓存刷新,并将缓存刷新周期设置为 1800 秒,即 30 分钟。 必须在每个 AD FS 节点上完成此配置,之后必须重启 AD FS 服务。 这些更改不会影响其他节点,在所有节点中进行更改之前会测试第一个节点。

  1. 导航到 AD FS 配置文件(默认位置为 C:\Windows\ADFS\Microsoft.IdentityServer.ServiceHost.exe.config)并在“Microsoft.IdentityServer.Service”节下添加以下条目:
  • backgroundCacheRefreshEnabled - 指定是否启用后台缓存功能。 “true/false”值。
  • cacheRefreshIntervalSecs - AD FS 刷新缓存的间隔值,以秒为单位。 如果 SQL 发生任何更改,AD FS 将刷新缓存。 AD FS 将收到 SQL 通知并刷新缓存。

注意

配置文件中的所有条目区分大小写。 <cache cacheRefreshIntervalSecs="1800" > backgroundCacheRefreshEnabled="true" />

支持的其他可配置值:

  • maxRelyingPartyEntries - AD FS 将在内存中保留的信赖方条目的最大数量。 oAuth 应用程序权限缓存也使用此值。 如果应用程序权限数量比 RP 多,并且所有权限都存储在内存中,则此值应是应用程序权限的数量。 默认值为 1000。
  • maxIdentityProviderEntries - 这是 AD FS 将在内存中保留的声明提供程序条目的最大数量。 默认值为 200。
  • maxClientEntries - 这是 AD FS 将在内存中保留的 OAuth 客户端条目的最大数量。 默认值为 500。
  • maxClaimDescriptorEntries - AD FS 将在内存中保留的声明描述符条目的最大数量。 默认值为 500。
  • maxNullEntries - 用作负缓存。 当 AD FS 在数据库中查找某个条目但未找到时,AD FS 将在负缓存中添加。 这是该缓存的最大大小。 每种类型的对象都有一个负缓存,它并非所有对象的单一缓存。 默认值为 50,0000。

跨数据中心的多项目数据库支持

对于多个数据中心的先前配置,AD FS 仅支持单个项目数据库,导致执行检索调用期间发生跨数据中心的延迟。

为了降低跨数据中心的延迟,AD FS 管理员现在可以部署多个项目数据库实例,然后修改 AD FS 节点的配置文件以指向不同的项目数据库实例。 可以在允许按节点项目数据库的配置文件中提供项目数据库连接字符串。 如果配置文件中没有连接字符串,则节点将回退到先前的设计,以使用配置数据库中存在的项目数据库。 此配置也支持混合环境。

要求

在设置多项目数据库支持之前,请在所有节点上运行更新并更新二进制文件,因为多节点调用是通过此功能发生的。

  1. 生成部署脚本以创建项目数据库:若要部署多个项目数据库实例,管理员需要为项目数据库生成 SQL 部署脚本。 作为此更新的一部分,现有的 Export-AdfsDeploymentSQLScript cmdlet 已更新,它可以选择性地采用一个参数来指定要为其生成 SQL 部署脚本的 AD FS 数据库。

例如,若要仅为项目数据库生成部署脚本,请指定 -DatabaseType 参数并传入值“Artifact”。 可选的 -DatabaseType 参数指定 AD FS 数据库类型,可设置为:All(默认值)、Artifact 或 Configuration。 如果未指定 -DatabaseType 参数,脚本将同时配置项目脚本和配置脚本。

PS C:\> Export-AdfsDeploymentSQLScript -DestinationFolder <script folder where scripts will be created> -ServiceAccountName <domain\serviceaccount> -DatabaseType "Artifact"

生成的脚本应在 SQL 计算机上运行,以创建所需的数据库并为 AD FS 服务帐户授予对这些数据库的 SQL SA 权限。

  1. 使用部署脚本创建项目数据库。 将新生成的 CreateDB.sql 和 SetPermissions.sql 部署脚本复制到 SQL 服务器计算机,然后执行这些脚本以创建本地项目数据库。

  2. 修改配置文件以添加项目数据库连接。 导航到 AD FS 节点的配置文件,在“Microsoft.IdentityServer.Service”节下,为新配置的项目数据库添加一个入口点。

注意

artifactStore 和 connectionString 是区分大小写的值。 请确保正确配置它们。 <artifactStore connectionString="Data Source=.\SQLInstance;Integrated Security=True;Initial Catalog=AdfsArtifactStore" />

使用与 SQL 连接匹配的数据源值。

  1. 重启 AD FS 服务,使更改生效。

注意

不建议在项目数据库之间使用 SQL 复制或同步。 建议为每个数据中心设置一个项目数据库。

跨数据中心故障转移和数据库恢复

建议在主项目数据库所在的同一数据中心内创建故障转移项目数据库。 如果发生故障转移,延迟不会提高。 不建议跨数据中心创建故障转移项目数据库。 下面详细说明如何使用多个项目数据库调用 OAuth、SAML、ESL 和令牌重播检测功能。

  • OAuth 和 SAML

    对于 OAuth 和 SAML 项目请求,节点将在配置文件中的项目数据库内创建项目。 如果配置文件不包含项目数据库连接,它将使用通用项目数据库。 当下一个项目提取请求进入另一个节点时,另一个节点将向第一个节点发出 REST API 调用,以从项目数据库中提取项目。 之所以需要这样做,是因为不同的节点可能有不同的项目数据库,而节点并不知道这一点。 如果第 1 个节点发生故障,则项目解析将会失败。 由于此设计,不需要跨不同的数据中心复制项目数据库。 如果整个数据中心发生故障(创建项目的节点很可能也会发生故障),则意味着不再可以解析项目。

  • Extranet 锁定

    配置文件中引用的项目数据库将用于 Extranet 锁定数据。 但是,如果使用 ESL 功能,AD FS 将选择一个主节点,它会将数据写入项目数据库。 所有节点向主节点发出 REST API 调用,以获取和设置有关每个用户的最新信息。 如果使用了多个项目数据库,管理员必须为每个项目数据库或数据中心选择一个主节点。

    若要选择一个节点作为 ESL 主节点,请导航到 AD FS 节点的配置文件,然后在“Microsoft.IdentityServer.Service”节下添加以下内容:

    在主节点上添加以下条目。 所有三个键都区分大小写。

    <useractivityfarmrole masterFQDN=[FQDN of the selected primary] isMaster="true"/>

    在其他节点上添加以下条目:

    <useractivityfarmrole masterFQDN=[FQDN of the selected primary] isMaster="false"/>

    注意

    由于多个项目数据库不会同步数据,ESL 值不会在项目数据库之间同步。 用户可能会为请求访问不同的数据中心,因此使 ExtranetLockoutThreshold 取决于项目数据库的数量,即 ExtranetLockoutThreshold * 项目数据库数量。

    • 令牌重播检测

      令牌重播检测数据始终从中心项目数据库调用。 AD FS 保存来自声明提供程序信任的令牌,确保无法重播同一令牌。 如果攻击者试图重播同一令牌,AD FS 将验证该令牌是否存在于项目数据库中。 如果该令牌存在,则拒绝请求。 中心项目数据库用于安全保护,由于项目数据库数据不被复制,攻击者可能会将请求发送到另一个数据中心并重播令牌。 在这种情况下,创建项目数据库的额外只读副本无法防止跨数据中心的延迟,因为只会使用中心项目数据库。