本文說明如何批次處理 API 呼叫,以減少用戶端必須建立的 HTTP 連線數量。
本文專門說明如何透過傳送 HTTP 要求來提交批次要求。如果您是使用 Google 用戶端程式庫提交批次要求,請參閱用戶端程式庫的說明文件。
總覽
用戶端建立的每個 HTTP 連線都會造成一定程度的負擔。Display & Video 360 API 支援批次作業,可以讓用戶端在單一 HTTP 要求中加入數個 API 呼叫。
以下是您可能想要使用批次作業的狀況範例:
- 擷取多位廣告主提供的資源。
- 大量建立或更新資源。
- 編輯多個委刊項的指定目標。
在任一案例中,都不需要個別傳送每一個呼叫,只需將這些呼叫分組後組成單一 HTTP 要求。所有內部要求都必須前往相同的 Google API。
單一批次要求最多能包含 1,000 個呼叫,如果您必須進行更多呼叫,請使用多個批次要求。
注意:Display & Video 360 API 的批次系統使用的語法與 OData 批次處理系統相同,但語意不同。
批次詳細資料
批次要求是由多個 API 呼叫合併成一個 HTTP 要求,系統會將這個要求傳送至 API 探索文件中指定的 batchPath
。預設路徑為 /batch/api_name/api_version
。本節詳細說明批次語法,並在後半段提供範例。
注意:組成批次的 n 個要求在用量限制中會算成 n 個要求,而不是一個要求。批次要求會先分解成一組要求再進行處理。
批次要求的格式
批次要求是單一標準 HTTP 要求,內含多個使用 multipart/mixed
內容類型的 Display & 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 要求。
回應批次要求
伺服器的回應是單一標準 HTTP 回應,具有 multipart/mixed
內容類型;每個部分都是對批次要求中某個要求的回應,並按照要求的順序排列。
就像要求中的分部一樣,每個回應分部都含有完整的 HTTP 回應,包括狀態碼、標頭和內文;就像要求中的部分一樣,每個回應部分前面都會加上 Content-Type
標頭,標示部分的開頭。
如果要求的特定部分含有 Content-ID
標頭,則回應的對應部分就會含有相符的 Content-ID
標頭,原始值前方會加上字串 response-
,如以下範例所示。
注意:伺服器可能會以任意順序執行您的呼叫。不要期望呼叫會按您的指定順序執行。如果您想要確保兩個呼叫依指定順序執行,就不能以單一要求傳送它們,而要先傳送第一個呼叫,然後等到第一個呼叫的回應後才能傳送第二個呼叫。
範例
以下範例說明如何使用 Display & Video 360 API 進行批次處理。
批次要求範例
POST /batch HTTP/1.1 Host: displayvideo.googleapis.com Authorization: Beareryour_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: Beareryour_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: Beareryour_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 用戶端程式庫提出批次要求。如要進一步瞭解如何安裝及設定程式庫,請參閱相關的快速入門指南。
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();
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()
$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);