Żądania wsadowe

W tym dokumencie opisujemy, jak grupować wywołania interfejsu API, by zmniejszyć liczbę połączeń HTTP, które musi nawiązać klient.

Ten dokument dotyczy tworzenia żądań zbiorczych przez wysyłanie żądań HTTP. Jeśli zamiast tego używasz biblioteki klienta Google do wysyłania żądania zbiorczego, zapoznaj się z dokumentacją biblioteki klienta.

Opis

Każde połączenie HTTP tworzone przez klienta wiąże się z określonym obciążeniem. Interfejs Display & Video 360 API obsługuje grupowanie, dzięki czemu klient może umieścić kilka wywołań interfejsu API w jednym żądaniu HTTP.

Przykłady sytuacji, w których warto użyć grupowania:

  • Pobieram zasoby od wielu reklamodawców.
  • Zbiorcze tworzenie i aktualizowanie zasobów.
  • Edytowanie kierowania w wielu elementach zamówienia.

W każdym przypadku zamiast wysyłać każde wywołanie osobno, możesz je zgrupować w jedno żądanie HTTP. Wszystkie żądania wewnętrzne muszą trafiać do tego samego interfejsu API Google.

Jedno żądanie zbiorcze może mieć maksymalnie 1000 wywołań. Jeśli musisz wykonać więcej wywołań, użyj wielu żądań zbiorczych.

Uwaga: system wsadowy dla interfejsu Display & Video 360 API korzysta z tej samej składni co system wsadowego przetwarzania zbiorczego OData, ale jego semantyka.

Szczegóły wsadu

Żądanie zbiorcze składa się z wielu wywołań interfejsu API połączonych w 1 żądanie HTTP, które można przesłać na adres batchPath podany w dokumencie opisującym interfejs API. Domyślna ścieżka to /batch/api_name/api_version. W tej sekcji szczegółowo opisujemy składnię wsadu. Później znajdziesz przykład.

Uwaga: zbiór żądań n zgrupowanych razem wlicza się do limitu wykorzystania jako żądania n, a nie jako jedno żądanie. Przed przetworzeniem żądanie zbiorcze jest dzielone na zbiór żądań.

Format żądania zbiorczego

Żądanie zbiorcze to pojedyncze standardowe żądanie HTTP zawierające wiele wywołań interfejsu API Display & Video 360, które używają typu treści multipart/mixed. Każda część głównego żądania HTTP zawiera zagnieżdżone żądanie HTTP.

Każda część zaczyna się od własnego nagłówka HTTP Content-Type: application/http. Może też mieć opcjonalny nagłówek Content-ID. Nagłówki części mają jednak służyć tylko do zaznaczania początku części. Są one niezależne od zagnieżdżonego żądania. Po rozpakowaniu żądania zbiorczego przez serwer do osobnych żądań nagłówki części są ignorowane.

Treść każdej części to kompletne żądanie HTTP z własnym czasownikiem, adresem URL, nagłówkami i treścią. Żądanie HTTP może zawierać tylko część ścieżki adresu URL. W żądaniach zbiorczych nie można używać pełnych adresów URL.

Nagłówki HTTP zewnętrznego żądania wsadowego, z wyjątkiem nagłówków Content-, takich jak Content-Type, mają zastosowanie do każdego żądania w grupie. Jeśli określisz nagłówek HTTP zarówno w żądaniu zewnętrznym, jak i w pojedynczym wywołaniu, wartość poszczególnych nagłówków zastąpi wartość nagłówka zewnętrznego żądania zbiorczego. Nagłówki pojedynczego wywołania mają zastosowanie tylko do tego wywołania.

Jeśli na przykład dla określonego wywołania podasz nagłówek Autoryzacja, będzie on stosowany tylko do tego wywołania. Jeśli podasz nagłówek autoryzacji dla żądania zewnętrznego, będzie on stosowany do wszystkich poszczególnych wywołań, chyba że zastąpi je własnymi nagłówkami autoryzacji.

Po otrzymaniu żądania zbiorczego serwer stosuje do każdej części parametry zapytania i nagłówki żądania zewnętrznego (stosownie do sytuacji), a następnie traktuje każdą część tak, jakby było to osobne żądanie HTTP.

Odpowiedź na żądanie zbiorcze

Odpowiedź serwera jest pojedynczą standardową odpowiedzią HTTP z typem treści multipart/mixed. Każda część to odpowiedź na jedno z żądań zbiorczych, w tej samej kolejności co żądania.

Podobnie jak części żądania, każda część odpowiedzi zawiera pełną odpowiedź HTTP wraz z kodem stanu, nagłówkami i treścią. Podobnie jak części żądania, każda odpowiedź jest poprzedzona nagłówkiem Content-Type oznaczającym początek części.

Jeśli dana część żądania miała nagłówek Content-ID, odpowiadająca jej część ma pasujący nagłówek Content-ID z pierwotną wartością poprzedzoną ciągiem response-, jak w poniższym przykładzie.

Uwaga: serwer może wykonywać wywołania w dowolnej kolejności. Nie licz na ich wykonanie w takiej kolejności, w jakiej zostały przez Ciebie określone. Jeśli chcesz mieć pewność, że w danej kolejności wystąpią 2 wywołania, nie możesz wysłać ich w jednym żądaniu. Zamiast tego wyślij pierwsze z nich osobno, a następnie poczekaj na odpowiedź na pierwsze, zanim wyślesz drugie.

Przykład

Przykład poniżej pokazuje wykorzystanie grupowania za pomocą interfejsu Display & Video 360 API.

Przykładowe żądanie zbiorcze

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--

Przykładowa odpowiedź zbiorcza

To jest odpowiedź na przykładowe żądanie z poprzedniej sekcji.

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--

Korzystanie z bibliotek klienta

Poniżej znajdziesz przykładowy kod pokazujący, jak tworzyć żądania zbiorcze za pomocą bibliotek klienta interfejsów API Google. Informacje o tym, jak zainstalować i skonfigurować biblioteki, znajdziesz w odpowiednim krótkim wprowadzeniu.

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);