我有一个可以同步数据源中的用户的系统。数据源由用户信息组成。同步新用户时,将触发PowerShell任务,该任务创建或更新用户。一切都很好,但是当新用户/更新用户的数量过多时,某些任务将失败,并出现一些有趣的错误,例如:
“服务器已返回以下错误:无效的枚举 上下文。”
或
“与要处理请求的目录的连接为 不可用。这可能是暂时情况。”
进行故障排除时,似乎很明显这些错误发生的原因是资源不足。这是因为所有同时触发的任务都在自己的PS会话上导入模块。
因此,我尝试了一些不同的事情并测量了Import-Module的速度等。因此,我得出结论,例如,运行Import-Module
然后运行Get-ADUser
更快,然后运行{{1} }(也将导入模块)。
Get-ADUser
平均时间340毫秒
Measure-Command {Import-Module ActiveDirectory}
平均时间420毫秒
Measure-Command {Get-ADUser -Filter *}
在导入模块后
平均时间10毫秒
但是这些边际差异并不能解决这个问题。所以我不得不进一步看。我发现禁用驱动器可能有助于加快此过程,因此在导入模块之前添加了以下内容:
Get-ADUser
平均时间85毫秒
快4倍!但是错误仍然在大量用户同时持续存在(例如50个任务)。因此,我考虑过轮询脚本中的可用性,或进行一个$Env:ADPS_LoadDefaultDrive = 0
Measure-Command {Import-Module ActiveDirectory}
循环。或者,可能需要重新设计触发单独任务的系统,以使其具有某种队列。
有人知道这种情况吗?还是他们想就此主题分享一些想法?
答案 0 :(得分:2)
这是因为所有同时触发的任务都在其自己的PS会话上导入模块。
然后,您需要确保不会发生这种情况,或者至少不要那么做,以免耗尽资源。因此,您有两种选择:
我认为选项2是更好的解决方案。例如,同步作业可以立即将用户名写入文件(甚至在内存中),而不是立即触发脚本,一旦找到所有用户,它就会触发PowerShell脚本并传递列表(或脚本)可以读取写入的文件)。您在那里有选择-最好的选择。
更新:所有.NET都可以在PowerShell中使用,因此另一种选择是更改整个脚本以使用.NET的DirectoryEntry
而不是ActiveDirectory模块,该模块将减少使用记忆。在PowerShell中甚至还有快捷方式。例如,[ADSI]"LDAP://$distinguishedName"
将为用户创建一个DirectoryEntry
对象。这是一个实质性的重写,但是性能(速度和内存消耗)要好得多。
以下是使用DirectorySearcher
(使用[ADSISearcher]
快捷方式)进行搜索的一些示例:https://blogs.technet.microsoft.com/heyscriptingguy/2010/08/23/use-the-directorysearcher-net-class-and-powershell-to-search-active-directory/
下面是使用DirectoryEntry
创建帐户的示例:https://www.petri.com/creating-active-directory-user-accounts-adsi-powershell