[改訂版] SharePoint Online HTTP 調整 (応答コード : 429) 対策の増分バックオフ リトライ
過去のブログ投稿でもご案内しておりますように、CSOM などのクライアント サイド API を利用するプログラムにおいて、HTTP 調整機能への対策として増分バックオフ リトライを実装することを推奨しています。
タイトル: PowerShell サンプル : SharePoint Online HTTP 調整 (応答コード : 429) 対策の増分バックオフ リトライ アドレス: https://blogs.technet.microsoft.com/sharepoint_support/2016/10/08/powershell-csom-sample-code-for-spo-http-429-incremental-backoff-retry/
従来弊社より案内していた増分バックオフ リトライのサンプル コードでは、Exponential Backoff というアルゴリズム (指数関数的にリトライ間隔を大きくする実装) を推奨していましたが、最新のベスト プラクティスにおいては、HTTP 応答の “Retry-After” ヘッダーの値を利用してリトライ間隔を指定する実装を推奨しています。本実装は、SharePoint Online だけでなく、Microsoft Graph API 等においても同様の推奨事項となります。
タイトル: SharePoint Online で調整またはブロックを回避する アドレス: /ja-jp/sharepoint/dev/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online
タイトル: Microsoft Graph throttling guidance
アドレス: https://developer.microsoft.com/en-us/graph/docs/concepts/throttling
本稿では、冒頭のブログで紹介している PowerShell で実装した増分バックオフ リトライを、最新のベスト プラクティスに変更したサンプルコードを紹介します。
HTTP 調整機能への対策としては、トラフィックの修飾 (User Agent の指定) も有効となりますので、併せてサンプルコードで実装しています。
$siteUrl = "https://tenant.sharepoint.com"
# 必要なアセンブリをロードします
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll";
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll";
# SPO に接続します
$script:context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl);
# ユーザー名入力を促します。
Write-Host "Please input user name : "
$username = Read-Host
# パスワード入力を促します。
Write-Host "Please input password : "
$password = Read-Host -AsSecureString
$creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password);
$script:context.Credentials = $creds;
# UserAgent を指定します。
$script:context.add_ExecutingWebRequest({
param ($source, $eventArgs);
$request = $eventArgs.WebRequestExecutor.WebRequest;
$request.UserAgent = "NONISV|Contoso|Application/1.0";
})
function ExecuteQueryWithIncrementalRetry {
param (
[parameter(Mandatory = $true)]
[int]$retryCount
);
$DefaultRetryAfterInMs = 120000;
$RetryAfterHeaderName = "Retry-After";
$retryAttempts = 0;
if ($retryCount -le 0) {
throw "Provide a retry count greater than zero."
}
while ($retryAttempts -lt $retryCount) {
try {
$script:context.ExecuteQuery();
return;
}
catch [System.Net.WebException] {
$response = $_.Exception.Response
if (($null -ne $response) -and (($response.StatusCode -eq 429) -or ($response.StatusCode -eq 503))) {
$retryAfterHeader = $response.GetResponseHeader($RetryAfterHeaderName);
$retryAfterInMs = $DefaultRetryAfterInMs;
if (-not [string]::IsNullOrEmpty($retryAfterHeader)) {
if (-not [int]::TryParse($retryAfterHeader, [ref]$retryAfterInMs)) {
$retryAfterInMs = $DefaultRetryAfterInMs;
}
else {
$retryAfterInMs *= 1000;
}
}
Write-Output ("CSOM request exceeded usage limits. Sleeping for {0} seconds before retrying." -F ($retryAfterInMs / 1000))
#Add delay.
Start-Sleep -m $retryAfterInMs
#Add to retry count.
$retryAttempts++;
}
else {
throw;
}
}
}
throw "Maximum retry attempts {0}, have been attempted." -F $retryCount;
}
# ここから実装したい任意のコードを書きます。
$web = $script:context.Web
$script:context.Load($web)
#$context.ExecuteQuery() を以下に置き換えます。
ExecuteQueryWithIncrementalRetry -retryCount 5
$web.Title = "RetryTest"
$web.Update()
#$context.ExecuteQuery() を以下に置き換えます。
ExecuteQueryWithIncrementalRetry -retryCount 5
今回の投稿は以上です。
本情報の内容は、作成日時点でのものであり、予告なく変更される場合があります。