過去のブログ投稿でもご案内しておりますように、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 で調整またはブロックを回避する
アドレス: https://docs.microsoft.com/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 FilesCommon FilesMicrosoft SharedWeb Server Extensions16ISAPIMicrosoft.SharePoint.Client.dll"; Add-Type -Path "C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions16ISAPIMicrosoft.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
今回の投稿は以上です。
本情報の内容は、作成日時点でのものであり、予告なく変更される場合があります。