バッチ リクエスト

Google Developers ブログで発表したように、バッチ処理の特定の手法であるグローバル HTTP バッチ エンドポイント(www.googleapis.com/batch)は 2020 年 8 月 12 日にシャットダウンされました。このページの残りの部分で説明するように、バッチ処理のその他のアプローチも引き続き使用できます。コードで Global HTTP バッチ エンドポイントを使用している場合は、API 固有の HTTP バッチ エンドポイント(www.googleapis.com/batch/API/VERSION)など、その他のアプローチへの移行手順が記載されたブログ投稿をご覧ください。

ここでは、複数のバッチ API 呼び出しを行って、クライアント側の HTTP 接続の回数を減らす方法について説明します。

このドキュメントでは、HTTP リクエストを送信してバッチ リクエストを作成する方法について説明します。Google クライアント ライブラリを使用してバッチ リクエストを行う場合は、クライアント ライブラリのドキュメントをご覧ください。

概要

クライアントで HTTP 接続を行うたびに、ある程度のオーバーヘッドが発生します。Google Mirror API はバッチ処理をサポートしているため、クライアントは複数の API 呼び出しを 1 つの HTTP リクエストにまとめることができます。

バッチ処理は次のような状況で使用します。

  • API の使用を開始したばかりで、アップロードするデータが大量にある。
  • アプリケーションがオフライン(インターネットに接続されていない状態)のときにユーザーがデータを変更したため、更新や削除の呼び出しを大量に送信してローカルデータとサーバー間で同期させる必要がある。

いずれの場合も、各呼び出しを個別に送信するのではなく、1 つの HTTP リクエストにまとめることができます。内部リクエストはすべて同じ Google API に送信する必要があります。

1 つのバッチ リクエストに含めることができる呼び出しは 1,000 回までです。これよりも多くの呼び出しを行う必要がある場合は、複数のバッチ リクエストを使用します。

: Google Mirror API のバッチシステムは OData バッチ処理システムと同じ構文を使用しますが、セマンティクスは異なります。

バッチ リクエストの詳細

バッチ リクエストは、複数の API 呼び出しを 1 つの HTTP リクエストにまとめたもので、API ディスカバリ ドキュメントで指定されている batchPath に送信できます。デフォルトのパスは /batch/api_name/api_version です。このセクションでは、バッチ リクエストの構文について詳しく説明し、最後にを紹介します。

: n 件のリクエストを 1 つにまとめたバッチ リクエストは、1 件のリクエストではなく n 件のリクエストとして使用量上限に加算されます。バッチ リクエストは、処理される前に一連のリクエストに分割されます。

バッチ リクエストの形式

バッチ リクエストは、複数の Google Mirror API 呼び出しを含む単一の標準 HTTP リクエストで、multipart/mixed コンテンツ タイプを使用します。そのメインの 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 番目の呼び出しを送信します。

次の例は、Google Mirror API によるバッチ処理の使用方法を示しています。

バッチ リクエストの例

POST /batch HTTP/1.1
Content-Length: content_length
content-type: multipart/mixed; boundary="===============7330845974216740156=="
accept-encoding: gzip, deflate

--===============7330845974216740156==
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: TIMELINE_INSERT_USER_1

POST /mirror/v1/timeline HTTP/1.1
Content-Type: application/json
authorization: Bearer user_1_token
accept: application/json
content-length: 24

{"text": "Hello there!"}
--===============7330845974216740156==
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: TIMELINE_INSERT_USER_2

POST /mirror/v1/timeline HTTP/1.1
Content-Type: application/json
authorization: Bearer user_2_token
accept: application/json
content-length: 24

{"text": "Hello there!"}
--===============7330845974216740156==
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: TIMELINE_INSERT_USER_3

POST /mirror/v1/timeline HTTP/1.1
Content-Type: application/json
authorization: Bearer user_3_token
accept: application/json
content-length: 24

{"text": "Hello there!"}
--===============7330845974216740156==--

バッチ レスポンスの例

これは、前のセクションのリクエスト例に対するレスポンスです。

HTTP/1.1 200 OK
Content-Type: multipart/mixed; boundary=batch_pK7JBAk73-E=_AA5eFwv4m2Q=
Date: Tue, 22 Jan 2013 18:56:00 GMT
Expires: Tue, 22 Jan 2013 18:56:00 GMT
Cache-Control: private, max-age=0

--batch_pK7JBAk73-E=_AA5eFwv4m2Q=
Content-Type: application/http
Content-ID: response-TIMELINE_INSERT_USER_1

HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 304

{
 "kind": "glass#timelineItem",
 "id": "1234567890",
 "selfLink": "https://www.googleapis.com/mirror/v1/timeline/1234567890",
 "created": "2012-09-25T23:28:43.192Z",
 "updated": "2012-09-25T23:28:43.192Z",
 "etag": "\"G5BI0RWvj-0jWdBrdWrPZV7xPKw/t25selcGS3uDEVT6FB09hAG-QQ\"",
 "text": "Hello there!"
}
--batch_pK7JBAk73-E=_AA5eFwv4m2Q=
Content-Type: application/http
Content-ID: response-TIMELINE_INSERT_USER_2

HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 304

{
 "kind": "glass#timelineItem",
 "id": "0987654321",
 "selfLink": "https://www.googleapis.com/mirror/v1/timeline/0987654321",
 "created": "2012-09-25T23:28:43.192Z",
 "updated": "2012-09-25T23:28:43.192Z",
 "etag": "\"G5BI0RWvj-0jWdBrdWrPZV7xPKw/t25selcGS3uDEVT6FB09hAG-QQ\"",
 "text": "Hello there!"
}
--batch_pK7JBAk73-E=_AA5eFwv4m2Q=
Content-Type: application/http
Content-ID: response-TIMELINE_INSERT_USER_3

HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 304

{
 "kind": "glass#timelineItem",
 "id": "5432109876",
 "selfLink": "https://www.googleapis.com/mirror/v1/timeline/5432109876",
 "created": "2012-09-25T23:28:43.192Z",
 "updated": "2012-09-25T23:28:43.192Z",
 "etag": "\"G5BI0RWvj-0jWdBrdWrPZV7xPKw/t25selcGS3uDEVT6FB09hAG-QQ\"",
 "text": "Hello there!"
}
--batch_pK7JBAk73-E=_AA5eFwv4m2Q=--