如何处理 LDAP 服务器 Cookie

在 LDAP 中,一些查询会生成大型结果集。 此类查询给 Windows Server 带来了一些难题。

收集和构建这些大型结果集是重要的工作。 许多属性需要从内部表示形式转换为 LDAP 网络表示形式。 对于许多属性而言,需要在响应帧中从内部格式(通常是二进制)转换为基于文本的 UTF-8 格式。

另一个难题是包含数万个对象的结果集需要大量存储空间,很容易几百兆字节。 这些需要大量的虚拟地址空间。 网络传输遇到问题,因为传输中的 TCP 会话出故障时,整个工作会丢失。

这些容量和物流问题促使 Microsoft LDAP 开发人员创建称为“分页查询”的 LDAP 扩展。 分页查询实现一个 LDAP 控件,用于将一个大型查询分解成多个较小的结果集块。 分页查询是 RFC 标准:RFC 2696

分页查询方法使用由客户端或通过 LDAP 策略(“MaxPageSize”)设置的页大小。 客户端始终需要通过发送 LDAP 控件来启用分页。

处理包含多个结果的查询时,在某一时刻会达到允许的最大对象数。 LDAP 服务器将打包响应消息,并添加包含稍后继续搜索所需信息的 Cookie。

客户端应用程序必须将 Cookie 视为不透明的 Blob。 它可以检索响应中的对象计数,并且可以根据 Cookie 的存在情况继续搜索。 继续搜索。 客户端将相同的查询发送到 LDAP 服务器,包括来自上一个响应的 Cookie 值。

如果对象数未填满页面,则 LDAP 查询已完成,并且响应将不包含页 Cookie。 如果服务器未返回任何 Cookie,则客户端必须认为分页搜索成功完成。

如果服务器返回错误,则客户端必须认为分页搜索未成功。 重试搜索会导致从第一页重新开始搜索。

Windows Server 将 Cookie 返回给客户端,并有时在服务器上存储与 Cookie 相关的信息。 此信息存储在服务器的缓存中,并受到某些限制的约束。

在这种情况下,由服务器发送到客户端的 Cookie 也用于从服务器的缓存中查找信息。 当客户端继续分页搜索时,Windows Server 使用客户端 Cookie 以及服务器 Cookie 缓存中的任何相关信息继续搜索。 如果由于任何原因服务器从服务器缓存中找不到相关 Cookie 信息,搜索将停止,并向客户端返回错误。

显然,LDAP 服务器一次为多个客户端提供服务。 此外,多个客户端可以一次启动需要使用服务器 Cookie 缓存的查询。 因此,在 Windows Server 实现中,会对 cookie 池的使用情况进行跟踪,并设置了限制,这样 cookie 池就不会占用太多资源。 管理员可以使用 LDAP 策略中的以下设置设置限制。 默认值和说明如下。

MinResultSets: 4

如果服务器 Cookie 缓存中的条目数小于 MinResultSets,LDAP 服务器将不会查看最大池大小。

MaxResultSetSize:262,144 字节

服务器上的总 Cookie 缓存大小不得超过 MaxResultSetSize 的最大值(以字节为单位)。 如果超过了,将从最旧的 Cookie 开始删除,直到该池小于 MaxResultSetSize 个字节或池中的 Cookie 数小于 MinResultSets 值。 使用默认设置时,如果仅存储了 3 条 Cookie,LDAP 服务器会认为 450KB 的池是正常的。

MaxResultSetsPerConn:10

LDAP 服务器不允许针对池中的每个 LDAP 连接有超过 MaxResultSetsPerConn 条 Cookie。

处理删除的 Cookie

在所有情况下,从 LDAP 服务器缓存中删除 Cookie 信息不会导致应用程序出现即时错误。 应用程序可以在另一次尝试中从头开始重新启动分页搜索,并完成它。 某些应用程序利用这种重试机制来添加稳健性。

某些应用程序可能会执行页搜索,但从不完成它。 此未完成的搜索可能会将条目保留在 LDAP 服务器 Cookie 缓存中,这些条目通过前面所述的机制进行处理。 此机制对于释放服务器上的内存以进行活动 LDAP 搜索至关重要。

在服务器上删除此类 Cookie 并且客户端使用此 Cookie 句柄继续搜索时,会发生什么情况? LDAP 服务器在服务器 Cookie 缓存中找不到 Cookie,并返回查询错误。 错误响应类似于:

00000057: LdapErr: DSID-xxxxxxxx, comment: Error processing control, data 0, v1db1

注意

“DSID”背后的十六进制值将因 LDAP 服务器二进制文件的内部版本而异。

LDAP 服务器能够通过 16 Ldap Interface中的目录 记录事件。 如果将此类别设为 2,则可以收到以下事件:

Log Name:      Directory Service
Source:        Microsoft-Windows-ActiveDirectory_DomainService
Event ID:      2898
Task Category: LDAP Interface
Level:         Information
Description:
Internal event: The LDAP server has reached the limit of the number of Result Sets it will maintain for a single connection.  A stored Result Set will be discarded.  This will result in a client being unable to continue a paged LDAP search.
Maximum number of Result Sets allowed per LDAP connection:
10
Current number of Result Sets for this LDAP connection:
11

User Action
The client should consider a more efficient search filter.  The limit for Maximum Result Sets per Connection may also be increased.

Log Name:      Directory Service
Source:        Microsoft-Windows-ActiveDirectory_DomainService
Event ID:      2899
Task Category: LDAP Interface
Level:         Information
Description:
Internal event: The LDAP server has exceeded the limit of the LDAP Maximum Result Set Size. A stored Result Set will be discarded. This will result in a client being unable to continue a paged LDAP search.

Number of result sets currently stored:
4
Current Result Set Size:
263504
Maximum Result Set Size:
262144
Size of single Result Set being discarded:
40876
User Action
The client should consider a more efficient search filter.  The limit for Maximum Result Set Size may also be increased.

这些事件发出“已删除存储的 Cookie”的信号。 它并不意味着客户端已发现 LDAP 错误,而只是 LDAP 服务器已达到缓存的管理限制。 在某些情况下,LDAP 客户端可能已放弃分页搜索,并可能永远不会发现该错误。

如果你在域中从未遇到 LDAP 搜索错误,则可能从不需要监视 LDAP 服务器页搜索 Cookie 池。 如果你在环境中看到 LDAP 页搜索相关错误,则可能遇到 Cookie 池管理员限制的问题。

事件 2898 和 2899 是了解 LDAP 服务器已达到管理员限制的唯一方式。 当你遇到控件处理错误导致的 LDAP 查询错误时,应考虑提高对一个或多个 LDAP 策略设置的上限。 可以在如何管理 Cookie 池部分找到限制,具体取决于你收到的事件。

如果你在 DC/LDAP 服务器上看到事件 2898,建议你将 MaxResultSetsPerConn 设为 25。 在单个 LDAP 连接上通常不会有超过 25 个并行分页搜索。 如果你仍看到事件 2898,请考虑调查遇到该错误的 LDAP 客户端应用程序。 怀疑是在检索更多分页结果时它不知何故停止响应了,将 Cookie 挂起,并重新启动一个新查询。 查看应用程序在某些时候是否有足够的 Cookie 来达到其目的。 还可以将 MaxResultSetsPerConn 的值增加到 25 以上。 当你看到事件 2899 记录在域控制器上时,计划会有所不同。 如果你的 DC/LDAP 服务器运行在具有足够内存(几 GB 的可用内存)的计算机上,建议你在 LDAP 服务器上将 MaxResultsetSize 设为 >=250MB。 此限制已足够大,甚至可以针对非常大的目录提供大量 LDAP 页搜索。

如果你在使用 250MB 或更大容量的池时仍看到事件 2899,则你很可能正在使用许多客户端频繁地查询大量对象并返回这些对象。 使用 Active Directory 数据收集器集可以帮你查找使 LDAP 服务器繁忙的重复性分页查询。 这些查询都会显示与所用的页大小匹配的“返回的条目”数。

如果可能,应该评审应用程序设计,实施频率、数据量较小且/或较少客户端实例查询此数据的其他方法。 如果你可以访问某些应用程序的源代码,请参阅创建高效的启用 AD 的应用程序,以获取有关了解应用程序访问 AD 的最佳方法的帮助。

如果不能更改查询行为,一种方法也会添加所需命名上下文的更多复制实例,重新分配客户端。 复制实例和分发客户端可以减少各 LDAP 服务器上的负载。