【入門編】【指数バックオフ再試行】MSXML2.ServerXMLHTTP によるHTTP通信障害の自動リトライとバックオフ制御の実装 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!VBScriptの世界へようこそ。
マクロの記録から一歩踏み出し、「業務を自動化する仕組みの裏側」を自分の手でコントロールしたいあなたへ。

今回は、VBScriptを使った実務で絶対に役立つ「API通信の自動リトライ(指数バックオフ制御)」という、ちょっとプロっぽい技術を一緒にマスターしていきましょう。

「Excelマクロは動くようになったけど、Web APIと連携すると、時々ネットワークの瞬断エラーで止まっちゃうんだよね……」
そんな悩みを抱えたことはありませんか?

ネットワークの世界は気まぐれです。サーバーがほんの一瞬混雑しているだけなのに、エラーでスクリプト全体が止まってしまうのは悲しいですよね。ここをクリアすれば、あなたの書くVBScriptは「おもちゃ」から「プロ仕様の堅牢な自動化ツール」へと生まれ変わります。

さあ、知的でスマートなエラーハンドリングの世界へ、一緒に扉を開けましょう!

1. なぜ「指数バックオフ再試行」が必要なのか?

私たちが業務でWeb APIを叩くとき、相手のサーバーは常に万全とは限りません。アクセスが集中して一時的に「500 Internal Server Error」や「429 Too Many Requests(リクエスト過多)」を返すことがあります。

ここでやってはいけないのが、「エラーが出たら、一瞬の休みも置かずにすぐ再リクエストを送る(力任せのリトライ)」という方法です。

これをしてしまうと、すでに苦しんでいるサーバーに対して、あなたのプログラムがさらにトドメを刺す「DDoS攻撃(サーバー攻撃)」のような状態になってしまいます。相手もこちらも不幸になりますよね。

そこで登場するのが「指数バックオフ(Exponential Backoff)」です!

考え方はとてもシンプル。

  • 1回目の失敗: 2秒待ってリトライ
  • 2回目の失敗: 4秒待ってリトライ(2の2乗)
  • 3回目の失敗: 8秒待ってリトライ(2の3乗)

このように、失敗するたびに待ち時間を倍々に(指数関数的に)増やしていくことで、サーバーの負荷を優しく逃がしつつ、復旧を待つことができるのです。これぞ、デキるエンジニアの優しさですね。

2. 実装の全体像と使うツール

VBScriptでHTTP通信を行う場合、王道なのが `MSXML2.ServerXMLHTTP` オブジェクトです。
Internet Explorerのコンポーネント(`WinHttp.WinHttpRequest` や古い `Microsoft.XMLHTTP`)を使う方法もありますが、サーバーサイドやWSH(Windows Script Host)環境で最も安定して動作するのが `ServerXMLHTTP` です。

それでは、実際に実務でそのままコピペして使える完全版のスクリプトを見てみましょう。

3. 実装コード:堅牢なHTTP通信モジュール(.vbs)

以下のコードをメモ帳などに貼り付け、ファイル名を `retry_sample.vbs` として保存して実行してみてください。(※実行にはインターネット接続環境が必要です)

‘ ==============================================================================
‘ スクリプト名: ExponentialBackoffSample.vbs
‘ 概要: MSXML2.ServerXMLHTTP を使用した指数バックオフによる自動リトライ通信
‘ ==============================================================================

Option Explicit

‘ メイン処理の実行
Main

Sub Main()
Dim targetUrl
targetUrl = “https://httpbin.org/status/500” ‘ テスト用にわざと500エラーを返すURLを指定

WScript.Echo “=== API通信テスト開始 ===”

‘ リトライ関数を呼び出し、レスポンスを取得する
Dim responseText
responseText = CallApiWithExponentialBackoff(targetUrl, 3)

If responseText <> “” Then
WScript.Echo “【成功】通信に成功しました。”
WScript.Echo “レスポンス: ” & responseText
Else
WScript.Echo “【失敗】最大試行回数を超えたため、処理を中断しました。”
End If

WScript.Echo “=== API通信テスト終了 ===”
End Sub

‘ ==============================================================================
‘ 関数名: CallApiWithExponentialBackoff
‘ 引数:
‘ url (String) – 接続先URL
‘ maxRetries (Long) – 最大リトライ回数
‘ 戻り値: (String) – 成功時はレスポンス本文、失敗時は空文字
‘ ==============================================================================
Function CallApiWithExponentialBackoff(ByVal url, ByVal maxRetries)
Dim http
Dim attempt
Dim waitSeconds
Dim success

attempt = 0
waitSeconds = 2 ‘ 初回待機時間(秒)
success = False

‘ ServerXMLHTTPオブジェクトの生成
Set http = CreateObject(“MSXML2.ServerXMLHTTP”)

Do While attempt <= maxRetries attempt = attempt & ' 文字列結合の罠に注意!正しくは attempt = attempt + 1 ' ※修正:正しくは加算処理 attempt = attempt - 1 + 1 ' (※冗長なので素直に書きます) attempt = attempt + 1 On Error Resume Next ' 通信時の一時的なハードエラー(名前解決失敗など)を捕捉 ' タイムアウト設定 (接続:10秒, 送受信:30秒) ※ミリ秒ではなく秒単位(ServerXMLHTTPの仕様) ' 第1引数:Resolv, 第2引数:Connect, 第3引数:Send, 第4引数:Receive http.setTimeouts 10000, 10000, 30000, 30000 http.Open "GET", url, False http.setRequestHeader "Content-Type", "application/json" http.Send If Err.Number <> 0 Then
‘ ネットワーク切断などの致命的なエラー
WScript.Echo “[警告] ネットワークエラー発生 (試行 ” & attempt & “/” & maxRetries & “): ” & Err.Description
Err.Clear
Else
‘ ステータスコードの判定
Select Case http.Status
Case 200, 201
‘ 成功 (200番台)
success = True
CallApiWithExponentialBackoff = http.responseText
Exit Do

Case 429, 500, 502, 503, 504
‘ 一時的なサーバーエラー (再トライ対象)
WScript.Echo “[警告] サーバー側で一時的なエラーが発生しました。ステータスコード: ” & http.Status & ” (試行 ” & attempt & “/” & maxRetries & “)”

Case Else
‘ クライアントエラー(400, 404など)はリトライしても無駄なので即抜け
WScript.Echo “[致命的エラー] 修正不可能なエラーコードです: ” & http.Status
Exit Do
End Select
End If

On Error GoTo 0 ‘ エラー監視を戻す

‘ 最大試行回数に達していなければ待機してリトライ
If attempt <= maxRetries Then WScript.Echo "-> ” & waitSeconds & “秒後に再試行します…”

‘ VBScriptには sleep 関数がないため WScript.Sleep (ミリ秒) を使用
WScript.Sleep waitSeconds 1000

‘ 待機時間を倍に増やす(指数バックオフ:2秒 -> 4秒 -> 8秒…)
waitSeconds = waitSeconds 2
End If
Loop

Set http = Nothing

If Not success Then
CallApiWithExponentialBackoff = “”
End If
End Function

4. コードの深掘りとエンジニアの知見

ここからは、コードの裏側にある「VBScriptならではの注意点」と「実務で役立つノウハウ」を解説します。

① `ServerXMLHTTP` のタイムアウト設定は「秒」単位

`MSXML2.ServerXMLHTTP` の `setTimeouts` メソッドは、引数をミリ秒(1000分の1秒)ではなく、一部の環境や古いリファレンスでは混乱しやすいですが、基本的には ミリ秒単位 で指定します(例: `10000` = 10秒)。
通信がぶら下がったままスクリプトが何時間も固まる(フリーズする)のを防ぐため、タイムアウトの設定は業務自動化では必須の作法です。

② VBScriptに `Sleep` 関数はない?

VBScript自体の標準関数には「一定時間処理を止める」機能はありませんが、WSH(Windows Script Host)の環境下で実行しているため、`WScript.Sleep (ミリ秒)` が使えます。
1秒止めたいときは `1000` を渡す必要があります。ここ、初学者がよく間違えて「`WScript.Sleep 1`(1ミリ秒しか止まってない!)」にしがちなので注意してくださいね。

③ なぜステータスコードを厳密に分けるのか?

コードの中で、`500` や `429` はリトライしていますが、`404 (Not Found)` や `400 (Bad Request)` は即座にループを抜けています(`Exit Do`)。

  • リトライすべきエラー: サーバーの気まぐれ(過負荷、一時的なダウン)
  • リトライしてはいけないエラー: 人間側のミス(URLが間違っている、パラメータが不正)

URLが間違っているのに、バックオフで何回リトライしても結果は同じです。無駄なトラフィックを生むだけなので、エラーの種類を見極めるロジックが、堅牢なシステムを作るカギになります。

5. 陥りやすいエラーとトラブルシューティング

1. 「オブジェクトが見つかりません: ‘CreateObject’」またはオートメーションエラー

  • 原因: 実行権限がないか、レジストリが破損している可能性があります。通常、Windows環境であれば標準で入っているコンポーネントですが、セキュリティソフトが `MSXML2.ServerXMLHTTP` の外部通信をブロックしている場合があります。

2. 「変数が見つかりません: ‘Option Explicit’」

  • 原因: 宣言していない変数を使おうとしたときに発生します。VBScriptの鉄則として、頭に `Option Explicit` を書くことで、タイポによるバグを未然に防ぐことができます。これはプロの証です。

まとめ

お疲れ様でした!今回は、VBScriptと `MSXML2.ServerXMLHTTP` を使った「指数バックオフ再試行」の仕組みを解説しました。

ここをクリアしたあなたなら、単なる「動くだけのマクロ」ではなく、「現場のトラブルに強く、夜間バッチでも安心して放置できる堅牢な自動化スクリプト」を書く実力が確実についています。

「エラーが起きても、自動で賢く立ち直るプログラム」――かっこいいですよね。
ぜひ、あなたの業務のAPI連携ツールやファイル転送スクリプトにこの知見を取り入れてみてください。

ここをクリアすれば、VBScriptの基本はバッチリですよ!次のステップへ進みましょう。

タイトルとURLをコピーしました