Mejorar el rendimiento

Este documento cubre algunas técnicas que puede utilizar para mejorar el rendimiento de su aplicación. En algunos casos, se utilizan ejemplos de otras API o API genéricas para ilustrar las ideas presentadas. Sin embargo, los mismos conceptos se aplican a la API de Compute Engine.

Compresión usando gzip

Una manera fácil y conveniente de reducir el ancho de banda necesario para cada solicitud es habilitar la compresión gzip. Aunque esto requiere tiempo adicional de CPU para descomprimir los resultados, la compensación con los costos de red generalmente hace que valga la pena.

Para recibir una respuesta codificada con gzip, debe hacer dos cosas: establecer un encabezado Accept-Encoding y modificar su agente de usuario para que contenga la cadena gzip . A continuación se muestra un ejemplo de encabezados HTTP formados correctamente para habilitar la compresión gzip:

Accept-Encoding: gzip
User-Agent: my program (gzip)

Trabajar con recursos parciales

Otra forma de mejorar el rendimiento de sus llamadas API es enviando y recibiendo solo la parte de los datos que le interesan. Esto permite que su aplicación evite transferir, analizar y almacenar campos innecesarios, de modo que pueda utilizar recursos como la red, la CPU y la memoria de manera más eficiente.

Hay dos tipos de solicitudes parciales:

  • Respuesta parcial : una solicitud en la que usted especifica qué campos incluir en la respuesta (use el parámetro de solicitud fields ).
  • Parche : una solicitud de actualización donde envía solo los campos que desea cambiar (use el verbo HTTP PATCH ).

En las siguientes secciones se proporcionan más detalles sobre cómo realizar solicitudes parciales.

Respuesta parcial

De forma predeterminada, el servidor devuelve la representación completa de un recurso después de procesar las solicitudes. Para un mejor rendimiento, puede pedirle al servidor que envíe solo los campos que realmente necesita y obtener una respuesta parcial .

Para solicitar una respuesta parcial, utilice el parámetro de solicitud fields para especificar los campos que desea que se devuelvan. Puede utilizar este parámetro con cualquier solicitud que devuelva datos de respuesta.

Tenga en cuenta que el parámetro fields solo afecta los datos de respuesta; no afecta los datos que necesita enviar, si corresponde. Para reducir la cantidad de datos que envía al modificar recursos, utilice una solicitud de parche .

Ejemplo

El siguiente ejemplo muestra el uso del parámetro fields con una API "demostración" genérica (ficticia).

Solicitud simple: esta solicitud HTTP GET omite el parámetro fields y devuelve el recurso completo.

https://www.googleapis.com/demo/v1

Respuesta completa del recurso: los datos completos del recurso incluyen los siguientes campos, junto con muchos otros que se han omitido por motivos de brevedad.

{
  "kind": "demo",
  ...
  "items": [
  {
    "title": "First title",
    "comment": "First comment.",
    "characteristics": {
      "length": "short",
      "accuracy": "high",
      "followers": ["Jo", "Will"],
    },
    "status": "active",
    ...
  },
  {
    "title": "Second title",
    "comment": "Second comment.",
    "characteristics": {
      "length": "long",
      "accuracy": "medium"
      "followers": [ ],
    },
    "status": "pending",
    ...
  },
  ...
  ]
}

Solicitud de respuesta parcial: la siguiente solicitud para este mismo recurso utiliza el parámetro fields para reducir significativamente la cantidad de datos devueltos.

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

Respuesta parcial: en respuesta a la solicitud anterior, el servidor devuelve una respuesta que contiene solo la información de tipo junto con una matriz de elementos reducida que incluye solo el título HTML y la información característica de longitud en cada elemento.

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

Tenga en cuenta que la respuesta es un objeto JSON que incluye solo los campos seleccionados y sus objetos principales adjuntos.

A continuación se tratan los detalles sobre cómo formatear el parámetro fields , seguidos de más detalles sobre qué se devuelve exactamente en la respuesta.

Resumen de sintaxis de parámetros de campos

El formato del valor del parámetro de solicitud fields se basa libremente en la sintaxis XPath. La sintaxis admitida se resume a continuación y se proporcionan ejemplos adicionales en la siguiente sección.

  • Utilice una lista separada por comas para seleccionar varios campos.
  • Utilice a/b para seleccionar un campo b que esté anidado dentro del campo a ; use a/b/c para seleccionar un campo c anidado dentro de b .

    Excepción: para las respuestas de API que utilizan envoltorios de "datos", donde la respuesta está anidada dentro de un objeto data que parece data: { ... } , no incluya " data " en la especificación fields . Incluir el objeto de datos con una especificación de campos como data/a/b provoca un error. En su lugar, simplemente use una especificación fields como a/b .

  • Utilice un subselector para solicitar un conjunto de subcampos específicos de matrices u objetos colocando expresiones entre paréntesis " ( ) ".

    Por ejemplo: fields=items(id,author/email) devuelve solo el ID del elemento y el correo electrónico del autor para cada elemento de la matriz de elementos. También puede especificar un único subcampo, donde fields=items(id) es equivalente a fields=items/id .

  • Utilice comodines en las selecciones de campos, si es necesario.

    Por ejemplo: fields=items/pagemap/* selecciona todos los objetos en un mapa de páginas.

Más ejemplos de uso del parámetro campos

Los ejemplos siguientes incluyen descripciones de cómo el valor del parámetro fields afecta la respuesta.

Nota: Al igual que con todos los valores de parámetros de consulta, el valor del parámetro fields debe estar codificado en URL. Para una mejor legibilidad, los ejemplos de este documento omiten la codificación.

Identifique los campos que desea que se devuelvan o realice selecciones de campos .
El valor del parámetro de solicitud fields es una lista de campos separados por comas y cada campo se especifica en relación con la raíz de la respuesta. Por lo tanto, si realiza una operación de lista , la respuesta es una colección y generalmente incluye una matriz de recursos. Si está realizando una operación que devuelve un único recurso, los campos se especifican en relación con ese recurso. Si el campo que selecciona es (o forma parte de) una matriz, el servidor devuelve la parte seleccionada de todos los elementos de la matriz.

A continuación se muestran algunos ejemplos a nivel de colección:
Ejemplos Efecto
items Devuelve todos los elementos de la matriz de elementos, incluidos todos los campos de cada elemento, pero ningún otro campo.
etag,items Devuelve tanto el campo etag como todos los elementos de la matriz de elementos.
items/title Devuelve solo el campo title para todos los elementos de la matriz de elementos.

Siempre que se devuelve un campo anidado, la respuesta incluye los objetos principales adjuntos. Los campos principales no incluyen ningún otro campo secundario a menos que también se seleccionen explícitamente.
context/facets/label Devuelve solo el campo label para todos los miembros de la matriz facets , que a su vez está anidada bajo el objeto context .
items/pagemap/*/title Para cada elemento de la matriz de elementos, devuelve solo el campo title (si está presente) de todos los objetos que son hijos de pagemap .

A continuación se muestran algunos ejemplos a nivel de recursos:
Ejemplos Efecto
title Devuelve el campo title del recurso solicitado.
author/uri Devuelve el subcampo uri del objeto de author en el recurso solicitado.
links/*/href
Devuelve el campo href de todos los objetos que son hijos de links .
Solicite solo partes de campos específicos utilizando subselecciones .
De forma predeterminada, si su solicitud especifica campos particulares, el servidor devuelve los objetos o elementos de la matriz en su totalidad. Puede especificar una respuesta que incluya solo ciertos subcampos. Esto se hace utilizando la sintaxis de subselección " ( ) ", como en el siguiente ejemplo.
Ejemplo Efecto
items(title,author/uri) Devuelve solo los valores del title y uri del autor para cada elemento de la matriz de elementos.

Manejo de respuestas parciales

Después de que un servidor procesa una solicitud válida que incluye el parámetro de consulta fields , devuelve un código de estado HTTP 200 OK , junto con los datos solicitados. Si el parámetro de consulta fields tiene un error o no es válido, el servidor devuelve un código de estado 400 Bad Request , junto con un mensaje de error que le indica al usuario cuál fue el problema con la selección de sus campos (por ejemplo, "Invalid field selection a/b" ).

Aquí está el ejemplo de respuesta parcial que se muestra en la sección introductoria anterior. La solicitud utiliza el parámetro fields para especificar qué campos devolver.

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

La respuesta parcial se ve así:

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

Nota: Para las API que admiten parámetros de consulta para la paginación de datos ( maxResults y nextPageToken , por ejemplo), utilice esos parámetros para reducir los resultados de cada consulta a un tamaño manejable. De lo contrario, es posible que no se obtengan las mejoras de rendimiento posibles con una respuesta parcial.

Parche (actualización parcial)

También puedes evitar enviar datos innecesarios al modificar recursos. Para enviar datos actualizados solo para los campos específicos que está cambiando, use el verbo HTTP PATCH . La semántica del parche descrita en este documento es diferente (y más simple) que la de la implementación anterior de actualización parcial de GData.

El breve ejemplo a continuación muestra cómo el uso del parche minimiza los datos que necesita enviar para realizar una pequeña actualización.

Ejemplo

Este ejemplo muestra una solicitud de parche simple para actualizar solo el título de un recurso API "de demostración" genérico (ficticio). El recurso también tiene un comentario, un conjunto de características, estado y muchos otros campos, pero esta solicitud solo envía el campo title , ya que ese es el único campo que se modifica:

PATCH https://www.googleapis.com/demo/v1/324
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "title": "New title"
}

Respuesta:

200 OK
{
  "title": "New title",
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "accuracy": "high",
    "followers": ["Jo", "Will"],
  },
  "status": "active",
  ...
}

El servidor devuelve un código de estado 200 OK , junto con la representación completa del recurso actualizado. Dado que solo se incluyó el campo title en la solicitud de parche, ese es el único valor que es diferente al anterior.

Nota: Si utiliza el parámetro fields de respuesta parcial en combinación con el parche, puede aumentar aún más la eficiencia de sus solicitudes de actualización. Una solicitud de parche solo reduce el tamaño de la solicitud. Una respuesta parcial reduce el tamaño de la respuesta. Entonces, para reducir la cantidad de datos enviados en ambas direcciones, use una solicitud de parche con el parámetro fields .

Semántica de una solicitud de parche

El cuerpo de la solicitud de parche incluye solo los campos de recursos que desea modificar. Cuando especifica un campo, debe incluir cualquier objeto principal adjunto, del mismo modo que los padres adjuntos se devuelven con una respuesta parcial . Los datos modificados que envía se fusionan con los datos del objeto principal, si lo hay.

  • Agregar: para agregar un campo que aún no existe, especifique el nuevo campo y su valor.
  • Modificar: para cambiar el valor de un campo existente, especifique el campo y configúrelo con el nuevo valor.
  • Eliminar: para eliminar un campo, especifique el campo y configúrelo en null . Por ejemplo, "comment": null . También puedes eliminar un objeto completo (si es mutable) configurándolo en null . Si está utilizando la biblioteca cliente API de Java , utilice Data.NULL_STRING en su lugar; Para obtener más información, consulte JSON nulo .

Nota sobre las matrices: las solicitudes de parches que contienen matrices reemplazan la matriz existente con la que usted proporciona. No puede modificar, agregar o eliminar elementos en una matriz de forma gradual.

Usando parche en un ciclo de lectura-modificación-escritura

Puede ser una práctica útil comenzar recuperando una respuesta parcial con los datos que desea modificar. Esto es especialmente importante para los recursos que utilizan ETags, ya que debe proporcionar el valor de ETag actual en el encabezado HTTP If-Match para poder actualizar el recurso correctamente. Después de obtener los datos, puede modificar los valores que desea cambiar y enviar la representación parcial modificada con una solicitud de parche. A continuación se muestra un ejemplo que supone que el recurso de demostración utiliza ETags:

GET https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token

Esta es la respuesta parcial:

200 OK
{
  "etag": "ETagString"
  "title": "New title"
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "level": "5",
    "followers": ["Jo", "Will"],
  }
}

La siguiente solicitud de parche se basa en esa respuesta. Como se muestra a continuación, también utiliza el parámetro fields para limitar los datos devueltos en la respuesta del parche:

PATCH https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json
If-Match: "ETagString"
{
  "etag": "ETagString"
  "title": "",                  /* Clear the value of the title by setting it to the empty string. */
  "comment": null,              /* Delete the comment by replacing its value with null. */
  "characteristics": {
    "length": "short",
    "level": "10",              /* Modify the level value. */
    "followers": ["Jo", "Liz"], /* Replace the followers array to delete Will and add Liz. */
    "accuracy": "high"          /* Add a new characteristic. */
  },
}

El servidor responde con un código de estado HTTP 200 OK y la representación parcial del recurso actualizado:

200 OK
{
  "etag": "newETagString"
  "title": "",                 /* Title is cleared; deleted comment field is missing. */
  "characteristics": {
    "length": "short",
    "level": "10",             /* Value is updated.*/
    "followers": ["Jo" "Liz"], /* New follower Liz is present; deleted Will is missing. */
    "accuracy": "high"         /* New characteristic is present. */
  }
}

Construyendo una solicitud de parche directamente

Para algunas solicitudes de parches, debe basarlas en los datos que recuperó anteriormente. Por ejemplo, si desea agregar un elemento a una matriz y no quiere perder ninguno de los elementos de la matriz existente, primero debe obtener los datos existentes. De manera similar, si una API usa ETags, debe enviar el valor de ETag anterior con su solicitud para poder actualizar el recurso correctamente.

Nota: Puede utilizar un encabezado HTTP "If-Match: *" para forzar la ejecución de un parche cuando se utilizan ETags. Si hace esto, no necesita leer antes de escribir.

Sin embargo, en otras situaciones, puede crear la solicitud de parche directamente, sin recuperar primero los datos existentes. Por ejemplo, puede configurar fácilmente una solicitud de parche que actualice un campo a un nuevo valor o agregue un nuevo campo. Aquí hay un ejemplo:

PATCH https://www.googleapis.com/demo/v1/324?fields=comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "comment": "A new comment",
  "characteristics": {
    "volume": "loud",
    "accuracy": null
  }
}

Con esta solicitud, si el campo comentario tiene un valor existente, el nuevo valor lo sobrescribe; de lo contrario, se establece en el nuevo valor. De manera similar, si existiera una característica de volumen, se sobrescribe su valor; si no, se crea. El campo de precisión, si está configurado, se elimina.

Manejo de la respuesta a un parche

Después de procesar una solicitud de parche válida, la API devuelve un código de respuesta HTTP 200 OK junto con la representación completa del recurso modificado. Si la API utiliza ETags, el servidor actualiza los valores de ETag cuando procesa con éxito una solicitud de parche, tal como lo hace con PUT .

La solicitud de parche devuelve la representación completa del recurso a menos que utilice el parámetro fields para reducir la cantidad de datos que devuelve.

Si una solicitud de parche da como resultado un nuevo estado de recurso que no es sintáctica o semánticamente inválido, el servidor devuelve un código de estado HTTP 400 Bad Request o 422 Unprocessable Entity y el estado del recurso permanece sin cambios. Por ejemplo, si intenta eliminar el valor de un campo obligatorio, el servidor devuelve un error.

Notación alternativa cuando no se admite el verbo HTTP PATCH

Si su firewall no permite solicitudes HTTP PATCH , realice una solicitud HTTP POST y configure el encabezado de anulación en PATCH , como se muestra a continuación:

POST https://www.googleapis.com/...
X-HTTP-Method-Override: PATCH
...

Diferencia entre parche y actualización

En la práctica, cuando envía datos para una solicitud de actualización que utiliza el verbo HTTP PUT , sólo necesita enviar aquellos campos que son obligatorios u opcionales; si envía valores para campos establecidos por el servidor, se ignoran. Aunque esto podría parecer otra forma de realizar una actualización parcial, este enfoque tiene algunas limitaciones. Con las actualizaciones que utilizan el verbo HTTP PUT , la solicitud falla si no proporciona los parámetros requeridos y borra los datos establecidos previamente si no proporciona parámetros opcionales.

Por este motivo, es mucho más seguro utilizar el parche. Sólo proporciona datos para los campos que desea cambiar; Los campos que omita no se borrarán. La única excepción a esta regla ocurre con elementos o matrices repetidos: si los omites todos, permanecen tal como están; si proporciona alguno de ellos, el conjunto completo se reemplaza por el conjunto que usted proporciona.