Solicitudes por lotes
Como resultado de la baja de los extremos HTTP globales por lotes, las solicitudes HTTP por lotes que se orientan solo a las API de BigQuery dejarán de funcionar el 1 de junio de 2021. Si tu aplicación envía solicitudes HTTP por lotes, reemplázalas por solicitudes HTTP individuales antes del 1 de junio de 2021.
Para obtener más información sobre la baja, consulta las siguientes Preguntas frecuentes. Para obtener documentación sobre cómo agrupar solicitudes HTTP por lotes, consulta Solicitudes por lotes.
Preguntas frecuentes sobre la baja de las solicitudes HTTP por lotes a las API de BigQuery
¿Por qué quedarán obsoletas las solicitudes HTTP por lotes de BigQuery?
La compatibilidad con extremos de lotes HTTP globales se basa en una arquitectura con un proxy único que recibe solicitudes para todas las API. A medida que Google se trasladó a una arquitectura más distribuida y de alto rendimiento en la que las solicitudes se dirigen directamente al servidor de API correspondiente, ya no pudimos admitir estos extremos globales.
Dar de baja las solicitudes HTTP de lotes de BigQuery es el siguiente paso. El servicio de BigQuery también está distribuido. Los backends dedicados controlan los métodos de QPS altas. Todas las regiones están aisladas, pero las solicitudes HTTP por lotes pueden provocar una distribución entre solicitudes interregionales. Esto hace que el procesamiento por lotes sea ineficiente y puede dar como resultado una latencia de procesamiento más alta, lo que se opone al objetivo original de la asistencia con solicitudes HTTP por lotes.
Específicamente, ¿qué funciones quedarán obsoletas?
Los siguientes métodos de solicitud por lotes para interactuar con las API de BigQuery dejarán de funcionar:
- La API de REST
batchPath
que se especifica en el documento de descubrimiento de la API. - La clase
BatchRequest
de la biblioteca cliente de Java - El objeto
Batch
de la biblioteca cliente de JavaScript - El objeto
BatchRequest
de la biblioteca cliente de C# - Otras bibliotecas cliente: clase
BatchRequest
¿Cómo migro?
La mayoría de los usuarios de BigQuery no utilizan solicitudes HTTP por lotes. Si aún usas solicitudes por lotes, usa los siguientes ejemplos para reemplazar las solicitudes HTTP en lotes por solicitudes HTTP individuales.
REST
Envía solicitudes HTTP individuales, como se documenta en la sección de referencia de la API de BigQuery.
No combines tus solicitudes en lotes con la ruta de acceso /batch/v2/bigquery
.
JavaScript
Si usas JavaScript, comenzarás con un bloque de código que se ve de la siguiente manera:
// Notice that the outer batch request contains inner API requests // for two different APIs. // Request to urlshortener API request1 = gapi.client.urlshortener.url.get({"shortUrl": "http://goo.gl/fbsS"}); // Request to zoo API request2 = gapi.client.zoo.animals.list(); // Request to urlshortener API request3 = gapi.client.urlshortener.url.get({"shortUrl": "https://goo.gl/XYFuPH"}); // Request to zoo API request4 = gapi.client.zoo.animal().get({"name": "giraffe"}); // Creating a batch request object batchRequest = gapi.client.newBatch(); // adding the 4 batch requests batchRequest.add(request1); batchRequest.add(request2); batchRequest.add(request3); batchRequest.add(request4); // print the batch request batchRequest.then(x=>console.log(x))
Reemplaza el bloque de código anterior con un bloque de código que se ve de la siguiente manera:
// Request to urlshortener API request1 = gapi.client.urlshortener.url.get({"shortUrl": "http://goo.gl/fbsS"}); // Request to zoo API request2 = gapi.client.zoo.animals.list(); // Request to urlshortener API request3 = gapi.client.urlshortener.url.get({"shortUrl": "http://goo.gl/fbsS"}) // Request to zoo API request4 = gapi.client.zoo.animals.list(); // print the 4 individual requests Promise.all([request1, request2, request3, request4]) .then(x=>console.log(x));
Python
Si usas Python, comenzarás con un bloque de código que se ve de la siguiente manera:
from apiclient.http import BatchHttpRequest def insert_animal(request_id, response, exception): if exception is not None: # Do something with the exception pass else: # Do something with the response pass service = build('farm', 'v2') batch = service.new_batch_http_request(callback=insert_animal) batch.add(service.animals().insert(name="sheep")) batch.add(service.animals().insert(name="pig")) batch.add(service.animals().insert(name="llama")) batch.execute(http=http)
Reemplaza el bloque de código anterior con un bloque de código que se ve de la siguiente manera:
# import a new API to create a thread pool from concurrent.futures import ThreadPoolExecutor as PoolExecutor def run_it(request): print(request.execute()) service = build('farm', 'v2') request1 = service.animals().insert(name="sheep") request2 = service.animals().insert(name="pig") request3 = service.animals().insert(name="llama") with PoolExecutor(max_workers=4) as executor: for _ in executor.map(run_it,[request1, request2, request3]): pass
Otros idiomas
Al igual que en los ejemplos anteriores, reemplaza las llamadas BatchRequest
por solicitudes individuales.
Obtén asistencia para la migración
Para obtener ayuda con la migración, puedes hacer preguntas en Stack Overflow. Los ingenieros de Google supervisan y responden las preguntas con la etiqueta google-bigquery. Usa esta etiqueta cuando hagas preguntas. Intentamos responder a todas las preguntas en un tiempo razonable.
Agrupación de solicitudes en lotes
En este documento, se muestra cómo agrupar llamadas a la API a fin de reducir la cantidad de conexiones HTTP que debe hacer el cliente.
Este documento trata, en particular, sobre cómo hacer una solicitud por lotes mediante el envío de una solicitud HTTP. Sin embargo, si usas una biblioteca cliente de Google para realizar una solicitud por lotes, debes consultar la documentación sobre bibliotecas cliente.
Descripción general
Cada conexión HTTP que tu cliente realiza da como resultado una cierta cantidad de sobrecarga. La API de BigQuery admite el procesamiento por lotes, a fin de permitir a tu cliente colocar varias llamadas a la API en una sola solicitud HTTP.
A continuación, se detallan algunos ejemplos de situaciones en las que te sería útil usar el procesamiento por lotes:
- Recién empiezas a utilizar la API y tienes muchos datos para cargar.
- Un usuario realizó cambios en datos mientras tu aplicación estaba sin conexión (desconectada de Internet), por lo que esta debe sincronizar sus datos locales con el servidor y, para ello, debe enviar muchas actualizaciones y eliminaciones.
En cada caso, en lugar de enviar cada llamada por separado, puedes agruparlas en una única solicitud HTTP. Todas las solicitudes internas deben ir en la misma API de Google.
Tienes un límite de 1,000 llamadas por cada solicitud por lote. Si necesitas hacer más llamadas, usa más solicitudes por lotes.
Nota: El sistema por lotes para la API de BigQuery emplea la misma sintaxis que el sistema de procesamiento por lotes OData, pero difiere en la semántica.
Detalles del lote
Una solicitud por lotes consta de varias llamadas a la API combinadas en una solicitud HTTP, que pueden enviarse al batchPath
especificado en el documento de descubrimiento de la API. La ruta de acceso predeterminada es /batch/api_name/api_version
. En esta sección, se describe la sintaxis del lote en detalle; más adelante, se muestra un ejemplo.
Nota: Un conjunto de solicitudes n agrupadas se considera en tu límite de uso como solicitudes n, no como una sola. La solicitud por lotes se divide en un conjunto de solicitudes antes de procesarse.
Formato de una solicitud por lotes
Una solicitud por lotes es una solicitud HTTP estándar que contiene múltiples llamadas a la API de BigQuery, con el tipo de contenido multipart/mixed
. Dentro de esa solicitud HTTP principal, cada una de las partes contiene una solicitud HTTP anidada.
Cada parte comienza con su propio encabezado HTTP Content-Type: application/http
. También puede tener un encabezado opcional Content-ID
. Sin embargo, los encabezados de partes solo están allí para marcar el comienzo de la parte; están separados de la solicitud anidada. Una vez que el servicio desenvuelve la solicitud por lotes en diferentes solicitudes, los encabezados de las partes se ignoran.
El cuerpo de cada parte es en sí mismo una solicitud HTTP completa, con su propio verbo, URL, encabezados y cuerpo. La solicitud HTTP debe contener solamente la parte de la ruta de la URL; no se admiten URL enteras en las solicitudes por lotes.
Los encabezados HTTP para la solicitud por lotes externa, excepto por los encabezados Content-
, como Content-Type
, se aplican a cada solicitud en el lote. Si especificas cierto encabezado HTTP tanto en la solicitud externa como en una llamada individual, el valor del encabezado de la llamada individual reemplaza el valor del encabezado de la solicitud por lotes externa. Los encabezados de una llamada individual solo se aplican a esa llamada.
Por ejemplo, si proporcionas un encabezado de autorización para una llamada específica, ese encabezado se aplica solamente a esa llamada. Si proporcionas un encabezado de autorización para la solicitud externa, se aplica a todas las llamadas individuales, a menos que la reemplacen con encabezados de autorización propios.
Cuando el servidor recibe la solicitud por lotes, aplica los encabezados y parámetros de consulta de la solicitud externa (según corresponda) a cada parte y, a continuación, trata cada parte como una solicitud HTTP separada.
Respuesta a una solicitud por lotes
La respuesta del servidor es una sola respuesta HTTP estándar con un tipo de contenido multipart/mixed
; cada parte es la respuesta a una de las solicitudes de la solicitud por lotes, en el mismo orden que las solicitudes.
Como las partes de la solicitud, cada parte de respuesta contiene una respuesta HTTP completa, que incluye un código de estado, encabezados y un cuerpo. Además, cada una está precedida por un encabezado Content-Type
que marca el comienzo de la parte.
Si cierta parte de la solicitud tenía un encabezado Content-ID
, la parte correspondiente de la respuesta tendrá un encabezado Content-ID
que coincida y un valor original precedido por la string response-
, como se muestra en el siguiente ejemplo.
Nota: Es posible que el servidor realice llamadas en cualquier orden. No cuentes con que se ejecutarán en el orden en que las especificaste. Si quieres garantizar que dos llamadas sucedan en un orden determinado, no puedes enviarlas en una misma solicitud; en cambio, envía la primera sola, espera una respuesta y, luego, envía la segunda.
Ejemplo
En el ejemplo siguiente, se demuestra el uso del procesamiento por lotes con una API de demostración genérica (ficticia) llamada API de Granja. Sin embargo, los mismos conceptos se aplican a la API de BigQuery.
Ejemplo de solicitud por lotes
POST /batch/farm/v1 HTTP/1.1 Authorization: Bearer your_auth_token Host: www.googleapis.com Content-Type: multipart/mixed; boundary=batch_foobarbaz Content-Length: total_content_length --batch_foobarbaz Content-Type: application/http Content-ID: <item1:12930812@barnyard.example.com> GET /farm/v1/animals/pony --batch_foobarbaz Content-Type: application/http Content-ID: <item2:12930812@barnyard.example.com> PUT /farm/v1/animals/sheep Content-Type: application/json Content-Length: part_content_length If-Match: "etag/sheep" { "animalName": "sheep", "animalAge": "5" "peltColor": "green", } --batch_foobarbaz Content-Type: application/http Content-ID: <item3:12930812@barnyard.example.com> GET /farm/v1/animals If-None-Match: "etag/animals" --batch_foobarbaz--
Ejemplo de respuesta por lotes
Esta es la respuesta a la solicitud de ejemplo de la sección anterior.
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@barnyard.example.com> HTTP/1.1 200 OK Content-Type application/json Content-Length: response_part_1_content_length ETag: "etag/pony" { "kind": "farm#animal", "etag": "etag/pony", "selfLink": "/farm/v1/animals/pony", "animalName": "pony", "animalAge": 34, "peltColor": "white" } --batch_foobarbaz Content-Type: application/http Content-ID: <response-item2:12930812@barnyard.example.com> HTTP/1.1 200 OK Content-Type: application/json Content-Length: response_part_2_content_length ETag: "etag/sheep" { "kind": "farm#animal", "etag": "etag/sheep", "selfLink": "/farm/v1/animals/sheep", "animalName": "sheep", "animalAge": 5, "peltColor": "green" } --batch_foobarbaz Content-Type: application/http Content-ID: <response-item3:12930812@barnyard.example.com> HTTP/1.1 304 Not Modified ETag: "etag/animals" --batch_foobarbaz--