Interrogation des modifications à l’aide d’USNChanged
Le contrôle DirSync est puissant et efficace, mais présente deux limitations importantes :
- Uniquement pour les applications hautement privilégiées : pour utiliser le contrôle DirSync, une application doit s’exécuter sous un compte disposant du privilège SE_SYNC_AGENT_NAME sur le contrôleur de domaine. Peu de comptes étant hautement privilégiés, une application qui utilise le contrôle DirSync ne peut pas être exécutée par des utilisateurs ordinaires.
- Aucune étendue de sous-arborescence : le contrôle DirSync retourne toutes les modifications qui se produisent dans un contexte de nommage. Une application qui s’intéresse uniquement aux modifications qui se produisent dans une petite sous-arborescence d’un contexte de nommage doit parcourir de nombreuses modifications non pertinentes, ce qui est inefficace à la fois pour l’application et pour le contrôleur de domaine.
Les modifications d’Active Directory peuvent également être obtenues en interrogeant l’attribut uSNChanged , ce qui évite les limitations du contrôle DirSync. Cette alternative n’est pas meilleure que le contrôle DirSync à tous égards, car elle implique la transmission de tous les attributs quand un attribut change et elle nécessite davantage de travail de la part du développeur d’application pour gérer correctement certains scénarios d’échec. Il s’agit actuellement de la meilleure façon d’écrire certaines applications de suivi des modifications.
Lorsqu’un contrôleur de domaine modifie un objet, il définit l’attribut uSNChanged de cet objet sur une valeur supérieure à la valeur précédente de l’attribut uSNChanged pour cet objet et supérieure à la valeur actuelle de l’attribut uSNChanged pour tous les autres objets détenus sur ce contrôleur de domaine. Par conséquent, une application peut trouver l’objet le plus récemment modifié sur un contrôleur de domaine en recherchant l’objet avec la plus grande valeur uSNChanged . Le deuxième objet le plus récemment modifié sur un contrôleur de domaine aura la deuxième plus grande valeur uSNChanged , et ainsi de suite.
L’attribut uSNChanged n’est pas répliqué. Par conséquent, la lecture de l’attribut uSNChanged d’un objet sur deux contrôleurs de domaine différents donne généralement des valeurs différentes.
Par exemple, l’attribut uSNChanged peut être utilisé pour suivre les modifications d’une sous-arborescence S. Tout d’abord, effectuez une « synchronisation complète » de la sous-arborescence S. Supposons que la plus grande valeur uSNChanged pour un objet dans S soit U. Interrogez périodiquement tous les objets de la sous-arborescence S dont la valeur uSNChanged est supérieure à U. La requête retourne tous les objets qui ont changé depuis la synchronisation complète. Définissez-vous sur le plus grand uSNChanged parmi ces objets modifiés, et vous êtes prêt à interroger à nouveau.
Les subtilités de l’implémentation d’une application de synchronisation uSNChanged sont les suivantes :
Utilisez l’attribut highestCommittedUSN de rootDSE pour lier vos filtres uSNChanged . Autrement dit, avant de démarrer une synchronisation complète, lisez le plus hautCommittedUSN de votre contrôleur de domaine affilié. Ensuite, effectuez une requête de synchronisation complète (à l’aide de résultats paginés) pour initialiser la base de données. Une fois cette opération terminée, stockez la valeur la plus élevéeCommittedUSN lue avant la requête de synchronisation complète ; à utiliser comme limites inférieures de l’attribut uSNChanged pour la synchronisation suivante. Plus tard, pour effectuer une synchronisation incrémentielle, relisez l’attribut rootDSE de highestCommittedUSN . Ensuite, interrogez les objets pertinents, à l’aide de résultats paginés, dont l’uSNChanged est supérieur aux limites inférieures de la valeur de l’attribut uSNChanged enregistrée à partir de la synchronisation précédente. Mettez à jour la base de données à l’aide de ces informations. Lorsque vous avez terminé, mettez à jour les limites inférieures de l’attribut uSNChanged à partir de la valeur highestCommittedUSN lue avant la requête de synchronisation incrémentielle. Stockez toujours les limites inférieures de la valeur de l’attribut uSNChanged dans le même stockage que celui que l’application synchronise avec le contenu du contrôleur de domaine.
En suivant cette procédure, plutôt que celle basée sur des valeurs uSNChanged sur les objets récupérés, évite que le serveur réexamine les objets mis à jour qui se trouvent en dehors du jeu applicable à l’application.
Étant donné que uSNChanged est un attribut non répliqué, l’application doit se lier au même contrôleur de domaine chaque fois qu’elle s’exécute. S’il ne peut pas être lié à ce contrôleur de domaine, il doit attendre qu’il puisse le faire, ou s’associer à un nouveau contrôleur de domaine et effectuer une synchronisation complète avec ce contrôleur de domaine. Lorsque l’application s’associe à un contrôleur de domaine, elle enregistre le nom DNS de ce contrôleur de domaine dans le stockage stable, qui est le même stockage, elle reste cohérente avec le contenu du contrôleur de domaine. Ensuite, il utilise le nom DNS stocké pour se lier au même contrôleur de domaine pour les synchronisations suivantes.
L’application doit détecter quand le contrôleur de domaine auquel elle est actuellement associée a été restauré à partir de la sauvegarde, car cela peut entraîner des incohérences. Lorsque l’application s’associe à un contrôleur de domaine, elle met en cache « l’ID d’appel » de ce contrôleur de domaine dans un stockage stable, c’est-à-dire que le même stockage reste cohérent avec le contenu du contrôleur de domaine. L'« ID d’appel » d’un contrôleur de domaine est un GUID stocké dans l’attribut invocationID de l’objet de service du contrôleur de domaine. Pour obtenir le nom unique de l’objet de service d’un contrôleur de domaine, lisez l’attribut dsServiceName du rootDSE.
N’oubliez pas que lorsque le stockage stable de l’application est restauré à partir de la sauvegarde, il n’y a aucun problème de cohérence, car le nom du contrôleur de domaine, l’ID d’appel et les limites inférieures de la valeur de l’attribut uSNChanged sont stockés avec les données synchronisées avec le contenu du contrôleur de domaine.
Utilisez la pagination lors de l’interrogation du serveur, à la fois des synchronisations complètes et incrémentielles, pour éviter la possibilité de récupérer simultanément des jeux de résultats volumineux. Pour plus d’informations, consultez Spécification d’autres options de recherche.
Exécutez des requêtes basées sur un index pour éviter de forcer le serveur à stocker des résultats intermédiaires volumineux lors de l’utilisation de résultats paginés. Pour plus d’informations, consultez Attributs indexés.
En général, n’utilisez pas de tri côté serveur des résultats de recherche, ce qui peut forcer le serveur à stocker et trier les résultats intermédiaires volumineux. Cela s’applique aux synchronisations complètes et incrémentielles. Pour plus d’informations, consultez Spécification d’autres options de recherche.
Ne gérez aucune condition parente correctement. L’application peut reconnaître un objet avant d’avoir reconnu son parent. Selon l’application, cela peut ou non être un problème. L’application peut toujours lire l’état actuel du parent à partir du répertoire.
Pour gérer les objets déplacés ou supprimés, stockez l’attribut objectGUID de chaque objet suivi. L’attribut objectGUID d’un objet reste inchangé, quel que soit l’emplacement où il est déplacé dans la forêt.
Pour gérer les objets déplacés, effectuez des synchronisations complètes périodiques ou augmentez l’étendue de la recherche et filtrez les modifications inintéressantes à l’extrémité du client.
Pour gérer les objets supprimés, effectuez des synchronisations complètes périodiques ou effectuez une recherche distincte d’objets supprimés lorsque vous effectuez une synchronisation incrémentielle. Lorsque vous interrogez des objets supprimés, récupérez l’objetGUID des objets supprimés pour déterminer les objets à supprimer de votre base de données. Pour plus d’informations, consultez Récupération d’objets supprimés.
N’oubliez pas que les résultats de la recherche incluent uniquement les objets et les attributs que l’appelant a l’autorisation de lire (en fonction des descripteurs de sécurité et des DACL sur les différents objets). Pour plus d’informations, consultez Effets de la sécurité sur les requêtes.
Pour plus d’informations et un exemple de code qui montre les principes de base d’une application de synchronisation USNChanged, consultez Exemple de code pour récupérer des modifications à l’aide d’USNChanged.