我有一个Powershell Azure Runbook,它通过一个大型存储帐户进行迭代,并在该帐户内的Blob上强制执行文件年龄策略。这可以正常运行,但会违反3个小时的公平份额政策。我可以使用混合工作程序,但我希望并行运行多个子运行手册,每个运行手册使用首字母前缀处理blob帐户的不同部分。
示例:
第一个子运行本运行A-M 第二:N-Z 第三名 第四:m-z
我正在考虑在循环中使用前缀变量,该循环将在字母之间进行迭代。
## Declaring the variables
$number_of_days_bak_threshold = 15
$number_of_days_trn_threshold = 2
$current_date = get-date
$date_before_blobs_to_be_deleted_bak = $current_date.AddDays(-$number_of_days_bak_threshold)
$date_before_blobs_to_be_deleted_trn = $current_date.AddDays(-$number_of_days_trn_threshold)
# Number of blobs deleted
$blob_count_deleted = 0
# Storage account details
$storage_account_name = <Account Name>
$storage_account_key = <Account Key>
$container = <Container>
## Creating Storage context for Source, destination and log storage accounts
$context = New-AzureStorageContext -StorageAccountName $storage_account_name -StorageAccountKey $storage_account_key
$blob_list = Get-AzureStorageBlob -Context $context -Container $container
## Creating log file
$log_file = "log-"+(get-date).ToString().Replace('/','-').Replace(' ','-').Replace(':','-') + ".txt"
$local_log_file_path = $env:temp + "\" + "log-"+(get-date).ToString().Replace('/','-').Replace(' ','-').Replace(':','-') + ".txt"
write-host "Log file saved as: " $local_log_file_path -ForegroundColor Green
## Iterate through each blob
foreach($blob_iterator in $blob_list){
$blob_date = [datetime]$blob_iterator.LastModified.UtcDateTime
# Check if the blob's last modified date is less than the threshold date for deletion for trn files:
if($blob_iterator.Name -Match ".trn") {
if($blob_date -le $date_before_blobs_to_be_deleted_trn) {
Write-Output "-----------------------------------" | Out-File $local_log_file_path -Append
write-output "Purging blob from Storage: " $blob_iterator.name | Out-File $local_log_file_path -Append
write-output " " | Out-File $local_log_file_path -Append
write-output "Last Modified Date of the Blob: " $blob_date | Out-File $local_log_file_path -Append
Write-Output "-----------------------------------" | Out-File $local_log_file_path -Append
# Cmdle to delete the blob
Remove-AzureStorageBlob -Container $container -Blob $blob_iterator.Name -Context $context
$blob_count_deleted += 1
Write-Output "Deleted "$extn
}
}
Elseif($blob_iterator.Name -Match ".bak") {
if($blob_date -le $date_before_blobs_to_be_deleted_bak) {
Write-Output "-----------------------------------" | Out-File $local_log_file_path -Append
write-output "Purging blob from Storage: " $blob_iterator.name | Out-File $local_log_file_path -Append
write-output " " | Out-File $local_log_file_path -Append
write-output "Last Modified Date of the Blob: " $blob_date | Out-File $local_log_file_path -Append
Write-Output "-----------------------------------" | Out-File $local_log_file_path -Append
# Cmdle to delete the blob
Remove-AzureStorageBlob -Container $container -Blob $blob_iterator.Name -Context $context
$blob_count_deleted += 1
Write-Output "Deleted "$extn
}
}
Else{
Write-Error "Unable to determine file type." $blob_iterator.Name
}
}
Write-Output "Blobs deleted: " $blob_count_deleted | Out-File $local_log_file_path -Append
我希望能够并行运行该帐户。
答案 0 :(得分:0)
因此,我同意@ 4c74356b41的观点,认为分解工作负载是最好的方法。但是,这本身并不总是听起来那么简单。下面,我描述了公平共享的各种变通方法以及我可以想到的潜在问题。它提供了大量信息,所以这里是重点:
TL; DR
无论如何,都有一些方法可以将顺序工作负载分解为顺序执行的作业,例如每个作业都在一个细分市场上工作,然后作为下一个操作开始下一个作业。 (就像一种递归。。)但是,管理顺序方法以正确处理间歇性故障可能会增加很多的复杂性。
如果可以将工作负载分解为不占用大量资源的较小的工作,则可以并行进行工作。换句话说,如果每个段所需的内存和套接字资源量很低,并且只要没有重叠或争用,则此方法应并行运行得更快。我还怀疑与此同时,合并的工作时间仍然少于顺序方法所需的时间。
有一个 gotcha 可以并行处理段...
当一堆属于同一帐户的AA作业一起启动时,它们将全部在同一沙箱实例中运行的趋势大大增加。沙盒永远不会与不相关的帐户共享,但是由于作业启动性能得到了改善,因此偏爱为同一帐户中的作业共享沙盒。当这些作业全部同时运行时,总沙箱资源配额将被达到,然后沙箱将立即执行硬退出的可能性增加。
此 gotcha 的原因,如果您的工作量是占用大量内存或套接字的,则您可能希望拥有一个父运行本来控制该设备的生命周期(即启动速度)。子手册。这产生了一种扭曲效果,即父级运行手册现在可能会达到公平份额的限制。
下一个解决方法是实现运行手册,这些手册在完成后将启动下一个处理段的作业。最好的方法是将下一个片段存储在作业可以检索到的位置,例如变量或Blob。这样,如果作业在其段中失败,只要有某种方法可以确保作业在整个工作负载完成之前一直运行,则所有工作最终都会完成。您可能要使用观察程序任务来验证最终完成并处理重试。一旦达到这种复杂性水平,您就可以尝试发现可以引入多少并行性而又不会达到资源限制。
如果您不必担心达到资源限制,可以考虑使用ThreadJob module on the PowerShell Gallery。使用这种方法,您仍将只有一个Runbook,但知道您将能够并行化该Runbook中的工作负载并在达到公平份额限制之前完成工作负载。如果单个任务既快速又轻便,这将非常有效。否则,这种方法可能会工作一小段时间,但是如果工作量增加了所需的时间或资源,就会开始失败。
请勿在AA作业中使用PowerShell作业来实现并行性。这包括使用诸如Parallel-ForEach
之类的命令 not 。有许多使用PowerShell Jobs的VM-Start/Stop
Runbook的示例; 这不是推荐的方法。 PowerShell作业需要大量资源来执行,因此使用PowerShell作业将显着增加您的AA作业所使用的资源以及达到内存配额的机会。
您可以通过将代码重新实现为Power Shell工作流并执行频繁的检查点来解决公平分配的限制。当工作流程作业达到公平分配的限制时,如果它一直在执行检查点,则它会将在另一个沙箱中重新启动,从最后一个检查点恢复。
我的回忆是您的工作需要每30分钟至少执行一次检查点。如果他们这样做,那将从<<公平地>永远中恢复公平份额而不会受到任何惩罚。 (以大量的工作时间为代价。)
即使没有检查点,也将在点击检查点后重试工作流程2次。因此,如果您的工作流程代码是幂等的,并且通过使用工作流程,它将迅速跳过以前完成的工作,即使没有检查点,您的工作也可能会完成(9小时之内)。
但是,工作流不仅仅是包装在workflow {}
脚本块中的Power Shell脚本:
将工作迁移到Azure Functions 。在最近发布的PowerShell函数中,这可能相对容易。功能将具有与自动化中不同的限制。这种差异可能很好地适合您的工作量,或更糟。我还没有尝试过“函数”方法,所以我不能说真的。
您将立即注意到的最明显区别是,与自动化相比,Functions是面向DevOps的原始服务。部分原因是自动化是一种更成熟的产品。 (自动化可能是第一个广泛可用的无服务器服务,大约在Lambda之前一年就已经推出。)自动化是专门为自动化云资源管理而构建的,自动化是功能选择的驱动因素。而功能是一种更为通用的无服务器操作方法。无论如何,目前有一个明显的区别是,Functions不对诸如RunAs帐户或Variables之类的东西提供任何内置支持。我希望功能会随着时间的推移在此特定方面有所改进,但是现在对于自动化任务来说这是非常基本的。