[改訂版] 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

 

 

今回の投稿は以上です。

本情報の内容は、作成日時点でのものであり、予告なく変更される場合があります。