批次處理要求

本文說明如何批次處理 API 呼叫,以減少 HTTP 連線數量 而非客戶需要做的事

本文專門說明如何透過傳送 HTTP 要求來提交批次要求。如果您是使用 Google 用戶端程式庫提交批次要求,請參閱用戶端程式庫的說明文件

總覽

用戶端的每個 HTTP 連線都會造成一定程度的負擔。顯示與Video 360 API 支援批次作業,可讓用戶端在單一 HTTP 要求中加入數個 API 呼叫。

以下是您可能想要使用批次作業的狀況範例:

  • 擷取多個廣告主的資源。
  • 大量建立或更新資源。
  • 編輯多個委刊項的指定目標。

在任一案例中,都不需要個別傳送每一個呼叫,只需將這些呼叫分組後組成單一 HTTP 要求。所有內部要求都必須前往相同的 Google API。

單一批次要求最多能包含 1,000 個呼叫。如果您發出的呼叫數量超過這個上限,請使用多個批次要求。

注意:Display &Video 360 的批次系統Video 360 API 使用的語法與 OData 批次處理系統相同,但語意不同。

批次詳細資料

批次要求是由多個 API 呼叫合併成一個 HTTP 要求,系統會將這個要求傳送至 API 探索文件中指定的 batchPath。預設路徑為 /batch/api_name/api_version。本節將詳細說明批次語法。後面還有範例

注意:一組批次處理的 n 要求將計入用量限制,並計為 n 要求,而非單一要求。在這個處理之前,批次要求會拆分成一組要求。

批次要求的格式

「批次要求」是單一標準 HTTP 要求,內含多個「多媒體和」使用 multipart/mixed 內容類型的 Video 360 API 呼叫。在主要 HTTP 要求中,每個分部都含有一個巢狀的 HTTP 要求。

每個部分都以自己的 Content-Type: application/http HTTP 標頭開始。也可以有選用的 Content-ID 標頭。但分部標頭只是用來標示部分開頭。內容與巢狀請求無關伺服器將批次要求解除包裝成個別要求後,系統會忽略該部分標頭。

每個部分的主體都是完整的 HTTP 要求,具有自己的動詞、網址、標頭和內文。HTTP 要求只能包含 URL 的路徑部分;批次要求禁止納入完整的 URL。

外部批次要求的 HTTP 標頭會套用於批次中的每項要求,但 Content- 標頭 (例如 Content-Type) 除外。如果您在外部要求和個別呼叫中均指定所提供的 HTTP 標頭,則個別呼叫標頭的值會覆寫外部批次要求標頭的值。個別呼叫的標頭只會套用於該呼叫。

例如,如果您提供 Authorization 標頭用於特定呼叫,則該標頭只會套用於該呼叫。如果您提供 Authorization 標頭用於外部要求,則除非個別呼叫以自己的 Authorization 標頭覆寫所提供的標頭,否則所提供的 Authorization 標頭會套用於所有個別呼叫。

當伺服器收到批次要求時,即會將外部要求的查詢參數和標頭 (在適用情況下) 套用至每一個分部,然後將每個分部視為不同的 HTTP 要求。

回應批次要求

伺服器回應是含有 multipart/mixed 內容類型的單一標準 HTTP 回應。每個部分都是回應批次要求中其中一個要求的回應,回應順序與要求順序相同。

就像要求中的分部一樣,每個回應分部都含有完整的 HTTP 回應,包括狀態碼、標頭和內文;如同要求的各個部分,每個回應部分的前面都會加上 Content-Type 標頭,用來標示該部分的開頭。

如果要求的指定部分有 Content-ID 標頭,則回應的對應部分會有相符的 Content-ID 標頭,且原始值在前面加上 response- 字串,如以下範例所示。

注意:伺服器可能會按任意順序執行呼叫。不要期望呼叫會按您的指定順序執行。如果您想要確保兩個呼叫依指定順序執行,就不能以單一要求傳送它們,而要先傳送第一個呼叫,然後等到第一個呼叫的回應後才能傳送第二個呼叫。

範例

以下範例顯示了透過多媒體廣告和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);