ここでは、複数のバッチ API 呼び出しを行って、クライアント側の HTTP 接続の回数を減らす方法について説明します。
具体的には、1 件の HTTP リクエストを送信してバッチ リクエストを行う方法を取り上げます。Google クライアント ライブラリを使用してバッチ リクエストを行う場合は、クライアント ライブラリのドキュメントをご覧ください。
概要
クライアントで HTTP 接続を行うたびに、ある程度のオーバーヘッドが発生します。Compute Engine API ではバッチ処理がサポートされており、クライアントは複数の API 呼び出しを 1 つの HTTP リクエストにまとめることができます。
バッチ処理は次のような状況で使用します。
- API の使用を開始したばかりで、アップロードするデータが大量にある。
- アプリケーションがオフライン(インターネットに接続されていない状態)のときにユーザーがデータを変更したため、更新や削除の呼び出しを大量に送信してローカルデータとサーバー間で同期させる必要がある。
いずれの場合も、各呼び出しを個別に送信するのではなく、1 つの HTTP リクエストにまとめることができます。内部リクエストはすべて同じ Google API に送信する必要があります。
1 つのバッチ リクエストに含めることができる呼び出しの上限は 1,000 個です。これ以上の呼び出しを行う必要がある場合は、バッチ リクエストを複数使用します。
注: Compute Engine API のバッチ処理システムで使用される構文は OData バッチ処理システムと同じものですが、セマンティクスは異なります。
バッチ リクエストの詳細
バッチ リクエストは、複数の API 呼び出しを 1 つの HTTP リクエストにまとめたもので、API ディスカバリ ドキュメントで指定されている batchPath に送信できます。デフォルトのパスは /batch/api_name/api_version です。このセクションでは、バッチ リクエストの構文について詳しく説明し、最後に例を紹介します。
注: n 件のリクエストを 1 つにまとめたバッチ リクエストは、1 件のリクエストではなく n 件のリクエストとして使用量上限に加算されます。バッチ リクエストは、個々のリクエストに分割されてから処理されます。
バッチ リクエストの形式
バッチ リクエストは multipart/mixed コンテンツ タイプを使用した単一の標準 HTTP リクエストで、複数の Compute Engine API 呼び出しから構成されます。そのメインの HTTP リクエスト内の各パーツには、ネストされた HTTP リクエストが含まれます。
各パーツはそれぞれ Content-Type: application/http という形式の HTTP ヘッダーで始まり、オプションの Content-ID ヘッダーを指定することもできます。ただし、パーツヘッダーはパーツの開始箇所を示すためだけに存在していて、ネストされたリクエストとは分かれています。サーバーがバッチ リクエストを別々のリクエストにアンラップした後、パーツヘッダーは無視されます。
各パーツのボディは、独自の動詞、URL、ヘッダー、ボディを含む完全な HTTP リクエストです。これらの HTTP リクエストには URL のパス部分のみを含める必要があり、完全な URL は、バッチ リクエストでは許可されていません。
外側のバッチ リクエストの HTTP ヘッダー(Content-Type などの Content- ヘッダー以外)はバッチ リクエスト内の各リクエストに適用されます。ある HTTP ヘッダーを外側のリクエストと個々の呼び出しの両方で指定した場合、個々の呼び出しのヘッダー値は外側のバッチ リクエストのヘッダー値を上書きします。個々の呼び出しのヘッダーはその呼び出しにのみ適用されます。
たとえば、ある呼び出しに Authorization ヘッダーを指定した場合、そのヘッダーはその呼び出しにのみ適用されます。Authorization ヘッダーを外側のリクエストに指定した場合、そのヘッダーはすべての呼び出しに適用されます。ただし、各呼び出しに独自の Authorization ヘッダーを指定している場合は各呼び出しの Authorization ヘッダーで上書きされます。
サーバーがバッチ リクエストを受信すると、外側のリクエストのクエリ パラメータとヘッダー(指定した場合)を各パーツに適用し、各パーツを個別の HTTP リクエストとして処理します。
バッチ リクエストへのレスポンス
サーバーのレスポンスは multipart/mixed コンテンツ タイプを使用した単一の標準 HTTP レスポンスです。各パーツはバッチ リクエスト内の個々のリクエストに対するレスポンスで、リクエストと同じ順序にネストされます。
レスポンスの各パーツは、リクエストのパーツと同様にステータス コード、ヘッダー、ボディを含む完全な HTTP レスポンスになっています。また、リクエストのパーツと同様に、レスポンスの各パーツはパーツの開始箇所を示す Content-Type ヘッダーから始まります。
リクエストのパーツに Content-ID ヘッダーがある場合、対応するレスポンスのパーツには、それに一致する Content-ID ヘッダーが指定されます。レスポンスのパーツのヘッダーは、以下の例に示すように、元の値の先頭に文字列 response- が付いた値となります。
注: サーバーはバッチ リクエスト内の呼び出しを順番どおりに処理するとは限りません。指定した順序で実行されると想定しないでください。2 つの呼び出しを特定の順序で実行したい場合は、1 つのバッチ リクエストで送信することはできません。代わりに、最初の呼び出しを送信してレスポンスが返ってきてから、2 番目の呼び出しを送信します。
例
次の例では、Farm API という一般的な(架空の)デモ API にバッチ処理を使用しています。同じ考え方が Compute Engine API にも当てはまります。
バッチ リクエストの例
POST /batch/farm/v1 HTTP/1.1
Authorization: Bearer your_auth_token
Host: www.googleapis.com
Content-Type: multipart/mixed; boundary=batch_foobarbaz
Content-Length: total_content_length
--batch_foobarbaz
Content-Type: application/http
Content-ID: <item1:12930812@barnyard.example.com>
GET /farm/v1/animals/pony
--batch_foobarbaz
Content-Type: application/http
Content-ID: <item2:12930812@barnyard.example.com>
PUT /farm/v1/animals/sheep
Content-Type: application/json
Content-Length: part_content_length
If-Match: "etag/sheep"
{
"animalName": "sheep",
"animalAge": "5"
"peltColor": "green",
}
--batch_foobarbaz
Content-Type: application/http
Content-ID: <item3:12930812@barnyard.example.com>
GET /farm/v1/animals
If-None-Match: "etag/animals"
--batch_foobarbaz--
バッチ レスポンスの例
これは、前のセクションのリクエスト例に対するレスポンスです。
HTTP/1.1 200
Content-Length: response_total_content_length
Content-Type: multipart/mixed; boundary=batch_foobarbaz
--batch_foobarbaz
Content-Type: application/http
Content-ID: <response-item1:12930812@barnyard.example.com>
HTTP/1.1 200 OK
Content-Type application/json
Content-Length: response_part_1_content_length
ETag: "etag/pony"
{
"kind": "farm#animal",
"etag": "etag/pony",
"selfLink": "/farm/v1/animals/pony",
"animalName": "pony",
"animalAge": 34,
"peltColor": "white"
}
--batch_foobarbaz
Content-Type: application/http
Content-ID: <response-item2:12930812@barnyard.example.com>
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: response_part_2_content_length
ETag: "etag/sheep"
{
"kind": "farm#animal",
"etag": "etag/sheep",
"selfLink": "/farm/v1/animals/sheep",
"animalName": "sheep",
"animalAge": 5,
"peltColor": "green"
}
--batch_foobarbaz
Content-Type: application/http
Content-ID: <response-item3:12930812@barnyard.example.com>
HTTP/1.1 304 Not Modified
ETag: "etag/animals"
--batch_foobarbaz--