リクエストのバッチ処理

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

具体的には、1 件の HTTP リクエストを送信してバッチ リクエストを行う方法を取り上げます。Google クライアント ライブラリを使用してバッチ リクエストを行う場合は、クライアント ライブラリのドキュメントをご覧ください。

概要

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

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

  • 複数の広告主のリソースを取得する。
  • リソースの一括作成または更新。
  • 複数の広告申込情報のターゲティングを編集しています。

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

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

: ディスプレイ &ビデオ 360 のバッチシステムVideo 360 API は OData バッチ処理システムと同じ構文を使用しますが、セマンティクスは異なります。

バッチ リクエストの詳細

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

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

バッチ リクエストの形式

バッチ リクエストは単一の標準 HTTP リクエストで、複数のディスプレイ &ビデオ 360 とVideo 360 API 呼び出し(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 番目の呼び出しを送信します。

次の例は、ディスプレイ &ビデオ 360 のバッチ処理とVideo 360 API。

バッチ リクエストの例

POST /batch HTTP/1.1
Host: displayvideo.googleapis.com
Authorization: Bearer your_auth_code
Content-Type: multipart/mixed; boundary=batch_foobarbaz
Content-Length: total_content_length

--batch_foobarbaz
Content-Type: application/http
Content-Transfer-Encoding: binary
MIME-Version: 1.0
Content-ID: <item1:12930812@displayvideo.example.com>

PATCH /v1/advertisers/advertiser_id?updateMask=displayName&fields=advertiserId,displayName HTTP/1.1
Content-Type: application/json; charset=UTF-8
Authorization: Bearer your_auth_code

{
  "displayName": "Updated Advertiser Name"
}
--batch_foobarbaz
Content-Type: application/http
Content-Transfer-Encoding: binary
MIME-Version: 1.0
Content-ID: <item2:12930812@displayvideo.example.com>

PATCH /v1/advertisers/advertiser_id/lineItems/line_item_id?updateMask=displayName&fields=lineItemId,displayName HTTP/1.1
Content-Type: application/json; charset=UTF-8
Authorization: Bearer your_auth_code

{
  "displayName": "Updated Line Item Name"
}

--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@displayvideo.example.com>

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: response_part_1_content_length

{
  "advertiserId": advertiser_id,
  "displayName": "Updated Advertiser Name"
}

--batch_foobarbaz
Content-Type: application/http
Content-ID: <response-item2:12930812@displayvideo.example.com>

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: response_part_2_content_length

{
  "lineItemId": line_item_id,
  "displayName": "Updated Line Item Name"
}

--batch_foobarbaz--

クライアント ライブラリの使用

次のコードサンプルは、 Google API クライアント ライブラリ。詳細については、それぞれのクイックスタート ガイドをご覧ください。 をご覧ください。

Java

Long advertiserId = advertiser-id;
List<Long> lineItemIds = Arrays.asList(line-item-id-1, line-item-id-2);

BatchRequest batch = service.batch();
JsonBatchCallback<LineItem> callback = new JsonBatchCallback<LineItem>() {
  public void onSuccess(LineItem lineItem, HttpHeaders responseHeaders) {
    System.out.printf("Line Item '%s' is now active.\n",
        lineItem.getName());
  }

  public void onFailure (GoogleJsonError error, HttpHeaders responseHeaders)
      throws IOException{
    System.out.printf("Error activating line item: %s\n", error.getMessage());
  }
};

LineItem activatedLineItem = new LineItem().setEntityStatus("ENTITY_STATUS_ACTIVE");

for (Long lineItemId: lineItemIds) {
  service.advertisers().lineItems().patch(advertiserId, lineItemId, activatedLineItem)
      .setUpdateMask("entityStatus").queue(batch, callback);
}
batch.execute();

Python

advertiser_id = advertiser-id
line_item_ids = [line-item-id-1, line-item-id-2]

def callback(request_id, response, exception):
    if exception is not None:
        print('Error activating line item "%s": %s' %
              request_id, exception)
    else:
        print('Line item "%s" is now active.' %
              response.get('name'))

batch = service.new_batch_http_request(callback=callback)

line_item_obj = {
    'entityStatus': 'ENTITY_STATUS_ACTIVE'
}

for line_item_id in line_item_ids:
    request = service.advertisers().lineItems().patch(
        advertiserId=advertiser_id,
        lineItemId=line_item_id,
        updateMask="entityStatus",
        body=line_item_obj
    )
    batch.add(request, request_id=line_item_id)

batch.execute()

PHP

$advertiserId = advertiser-id;
$lineItemIds = array(line-item-id-1, line-item-id-2);

// Enable batching on client and create current batch
$service->getClient()->setUseBatch(true);
$batch = $service->createBatch();

// Create line item with updated fields
$updatedLineItem = new Google_Service_DisplayVideo_LineItem();
$updatedLineItem->setEntityStatus('ENTITY_STATUS_ACTIVE');

// Create request parameter array with update mask
$optParams = array('updateMask' => 'entityStatus');

// Add each patch request to the batch
foreach($lineItemIds as $lineItemId) {
    $request = $this->service->advertisers_lineItems->patch(
        $advertiserId,
        $lineItemId,
        $updatedLineItem,
        $optParams
    );
    $requestId = $lineItemId;
    $batch->add($request, $requestId);
}

// Execute batch request
$results = $batch->execute();

// Iterate through results
foreach($results as $responseId => $lineItem) {
    $lineItemId = substr($responseId, strlen('response-') + 1);
    if ($lineItem instanceof Google_Service_Exception) {
        $e = $lineItem;
        printf(
            "Error activating line item '%s': %s\n",
            $lineItemId,
            $e->getMessage()
        );
    } else {
        printf("Line item '%s' is now active.\n", $lineItem->getName());
    }
}
$service->getClient()->setUseBatch(false);