本文档介绍了如何对 API 调用进行批处理以减少客户端必须建立的 HTTP 连接数量。
本文档专门介绍了如何通过发送 HTTP 请求来发出批处理请求。如果您要使用某个 Google 客户端库来发出批处理请求,请参阅该客户端库的说明文档。
概览
客户端建立的每个 HTTP 连接都会产生一定的开销。展示广告与Video 360 API 支持批处理,这样您的客户端就可以将多个 API 调用组合为一个 HTTP 请求。
在以下示例情况下,您可能需要使用批处理:
- 检索多个广告客户的资源。
- 批量创建或更新资源。
- 修改多个订单项的定位条件。
在上述每种情况下,您都可以将这些调用组合成一个 HTTP 请求,而不是单独发送每个调用。请注意,所有内部请求都必须发送到同一 Google API。
单个批量请求最多可以包含 1000 次调用。如果必须进行更多次调用,请使用多个批量请求。
注意:批处理系统用于展示广告和Video 360 API 使用的语法与 OData 批处理系统相同,但语义有所不同。
批量详情
批量请求就是将多个 API 调用进行合并而形成的一个 HTTP 请求,您可以将此请求发送到 API 发现文档中指定的 batchPath
。默认路径为 /batch/api_name/api_version
。本部分详细介绍了批处理语法,随后还会提供一个示例。
注意:一组一起进行批处理的 n 个请求将按 n 个请求(而非一个请求)计入用量限额。在处理之前,系统会将批量请求拆分为一组请求。
批量请求的格式
批量请求是一个标准 HTTP 请求,包含多个展示广告和Video 360 API 调用,使用 multipart/mixed
内容类型。在此主 HTTP 请求中,每个部分都包含一个内嵌的 HTTP 请求。
各个部分都以其自身的 Content-Type: application/http
标头开头。您还可以选择添加一个 Content-ID
标头。不过,每个部分的标头仅用于标记该部分的开头,而与嵌套请求无关。在服务器将批量请求拆分为多个单独请求之后,每个部分的标头就会被忽略。
各个部分的正文是一个完整的 HTTP 请求,各自有专用的动词、网址、标头和正文。此 HTTP 请求必须仅包含网址的路径部分;不允许在批量请求中使用完整的网址。
外部批量请求的 HTTP 标头应用于批次中的每个请求,但 Content-Type
之类的 Content-
标头除外。如果您在外部请求和个别调用中都指定了特定的 HTTP 标头,则个别调用标头的值将替换外部批量请求标头的值。另请注意,单个调用的标头仅应用于该调用本身。
例如,如果您为特定调用提供了 Authorization 标头,则该标头仅应用于该调用。如果您为外部请求提供了 Authorization 标头,则该标头将应用于所有的单个调用,除非单个调用将其替换为自身的 Authorization 标头。
当服务器收到批处理请求时,会将外部请求的查询参数和标头(如果适用)应用于各部分,然后将各部分视作单独的 HTTP 请求进行处理。
对批量请求的响应
服务器的响应是一个标准的 HTTP 响应,使用 multipart/mixed
内容类型;其中的每个部分分别是对批量请求中一个请求的响应,且顺序与这些请求相同。
和请求中的各部分一样,响应中的各部分都包含一个完整的 HTTP 响应,其中包括状态代码、标头和正文。此外,和请求中的各部分一样,响应中的各部分均以 Content-Type
标头为前缀,用于标记各部分的开头。
如果请求的某个特定部分具有 Content-ID
标头,则响应的对应部分也会有相同的 Content-ID
标头,其格式为在原始值前面加上 response-
字符串,如下例所示。
注意:服务器可能会以任何顺序执行您的调用,因此不要预期这些调用将会以您指定的顺序执行。如果要确保两个调用以指定顺序执行,就不能在单个请求中发送这两个调用。正确的做法是,先单独发送第一个调用,等收到其响应之后再发送第二个。
示例
以下示例展示了如何将批量处理与 Display &Video 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);