背景
业务对接AD过程中,当应用程序在某个时刻点对AD中的数据进行全量同步后,我们还需要时不时的去拉取AD在后续时刻中变更过的数据,保持应用程序和AD中数据的一致性。本文对两种实现AD增量数据同步的方法进行了一个对比和分析总结,以供参考。
方法一:DirSync Control方式
AD技术方案介绍文档:《Polling for Changes Using the DirSync Control》
AD处理细节见文档:《 Process DirSync Search Request》
DirSync Control方式属于LDAP Search操作中支持的一个LDAP扩展能力,通过指定对应的Request Control来查找AD服务器在上一个时刻点以后的变更数据。
该RequestControl对应的OID取值为:1.2.840.113556.1.4.841;对应的扩展名称为:LDAP_SERVER_DIRSYNC_OID。
其对应的运行流程如下所示:
其对应的LDAP Search Request参数注意事项如下:
参数 | 描述 |
---|---|
search base DN | DirSync Search必须指定Naming Context(Directory Partition)的Root节点,可以是domain partition,也可以是configuration partition等。如果不是指定Root节点,AD会返回如下报错:[LDAP: error code 53 - Unwilling To Perform]。 |
search scope | DirSync Search必须指定 sub_tree模式,也就是整个子树模式。 |
search filter | 可以指定任何有效的Filter表达式。第一次进行DirSync Search的时候,AD会返回所有符合Filter条件的对象及其属性。在随后指定有效的Cookie进行查询时,只会返回满足Filter条件,并只包含有变化的属性信息。 |
attributes | 同Search filter,可以随意指定任何关心的属性。第一次进行DirSync Search的时候,AD会返回所有符合Filter条件的对象及其要求的属性。在随后指定有效的Cookie进行查询时,只会返回满足Filter条件,并只包含有变化的属性信息。只有ObjectGUID和instanceType属性是在每次查询时都会返回。 |
几个注意事项和最佳实践:
- 为了使用DirSync control,AD要求应用程序使用的账号必须具备两个权限:“directory get changes”和“DS-Replication-Get-Changes”;这通常是Administrator和LocalSystem账号才具备的。如果对应的账号不具备权限,AD会返回如下报错:[LDAP: error code 53 - Unwilling To Perform];
- 应用程序必须不透明的处理Cookie,不能假设Cookie中包含任何有效信息;
- 涉及到AD DC复制场景时:
a. DC节点一生成的Cookie可能被DC节点二接受,但是DC节点二可能会返回重复的增量数据,也就是你可能已经查询过某些对象的修改,甚至应用程序已经处理过这些对象的最新状态的修改,而当前的返回会覆盖掉最新修改。应用程序应该忽略这种状况,以AD返回的为准,因为AD自身的复制会推动数据走向最终一致;
b. DC节点一生成的Cookie可能被DC节点二拒绝,这个在不同的AD版本中是很有可能的;具体处理方式就是捕获对应异常然后重试;
c. 还有考虑到有的数据变更可能在AD DC之间没有完成复制的时候,应用程序是获取不到的;同时这意味着,不管对一个对象做多少次修改,只会返回一次最终的变化结果; - 如果父节点进行移动或者重命名,其对应的子节点并不会产生变更数据,即使他们的DistinguishedName已经发生变化;
- 一定要使用objectGUID来标识和追踪一个对象的变化,因为其它属性都会变化,只有objectGUID是不变的;
- 关于Deleted Object获取问题:DirSync默认是返回删除节点信息的,但是会出现一种情况,删除节点在存活的时候是符合Filter条件的,而节点被删除之后不符合Filter条件,因此无法获取到对应节点的删除操作变更。这要求我们的应用程序实现的时候,需要考虑对应Filter的条件设置;
最后一个重点,Cookie是可以被重用的:
方法二:使用uSNChanged属性来获取增量数据
USN-Changed属性介绍:《a-usnchanged》
USN:The update sequence number。
当一个对象发生变化时,对应的uSNChanged属性也会跟着变化,类似于最后更新时间。域控制器修改某个对象时,会把对象的这个属性设置为比当前域控制器中最大uSNChanged值还大的一个值,并在RootDSE节点中进行存储,因此应用程序可以通过查找具有最大uSNChanged值的对象来找到域控制器上最近更改的对象(域控制器中第二个最近更改的对象将具有第二个最大的uSNChanged值,以此类推)。
提醒,这个序列号只在本地服务器中存储,意味着这不是一个在AD DC之间复制的属性,这对应用程序选择增量同步方案影响很重要。
其对应的方案运行流程如下:
几个注意事项和最佳实现:
- uSNChanged不是一个复制属性,所以必须绑定到同一个AD DC服务节点。如果对应的DC节点挂了,那此时应用程序的增量同步不可用,应该等待对应的DC节点恢复;
- uSNChanged的Filter查询方式,会返回满足条件的对象的所有属性,而不是只有变化的属性;同时,因为这个方法只是一个普通的Search查询,所以对应的search base DN就可以随意指定了,应用程序可以只指定感兴趣的变更节点范围;
- 必须使用paging control,避免返回大量的查询数据,或者导致AD返回CountLimit报错;
- 需要优雅的处理子节点数据比父节点数据提前返回场景,比如说:先创建了一个A节点,然后又在A下创建了一个B子节点,然后A节点又做了一次修改操作,这个时候B节点的uSNChanged是小于A节点的。应用程序可能先读取到B节点,然后才是A节点,这要求应用程序能够优雅处理这种Case,每次都去读取父节点的最新状态;
- 同DirSync Search,一定要使用objectGUID来标识和追踪一个对象的变化,因为其它属性都会变化,只有objectGUID是不变的;
- 怎么处理删除节点,通过uSNChanged是不能获取到删除节点的,因为对应的节点被移动到了回收站中。有如下两种方式进行处理:
a. 周期性的进行一次全量同步,这样子能够知道哪些节点被删除掉了;
b. 单独进行一次Deleted Objects的查询;
两种方法对比
在Microsoft的官方文档中也指出,这两种方法没有高下之分,怎么选择取决于应用程序的需求,其中的差异性可见如下表格:
差异点 | 方法一:DirSync Search | 方法二:uSNChanged |
---|---|---|
Caller账号 | Administrator or LocalSystem。要求具备两个权限:“directory get changes”和“DS-Replication-Get-Changes” | 不限制 |
search base DN | 必须是Naming Context的Root节点 | 不限制,应用程序可以随意指定感兴趣的范围 |
search filter | 随意指定 | 随意指定,但必须包含uSNChanged属性 |
search scope | sub_tree | 随意指定 |
父子节点顺序 | 可以要求AD必须先返回父节点变更数据,再返回子节点变更数据 | 随机返回 |
属性 | 只返回有变化的属性 | 要求的全部属性 |
AD DC复制 | 支持绑定到不同的DC服务节点 | 不支持 |