Consejos para aumentar el rendimiento

En este documento se tratan algunas técnicas que puedes usar para mejorar el rendimiento de tu aplicación. En algunos casos, se usan ejemplos de otras API o API genéricas para ilustrar las ideas presentadas. Sin embargo, se pueden aplicar los mismos conceptos a la API de Google Analytics.

Usar gzip

Una forma sencilla y cómoda de reducir el ancho de banda necesario para cada solicitud consiste en habilitar la compresión gzip. Aunque esto requiere tiempo de CPU adicional para descomprimir los resultados, la compensación con los costes de red normalmente hace que merezca la pena.

Para recibir una respuesta con codificación gzip debes hacer dos cosas: establecer un encabezado Accept-Encoding y modificar su user-agent para que incluya la cadena gzip. A continuación, te mostramos un ejemplo de encabezados HTTP con formato correcto 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 las llamadas de API es enviando y recibiendosolo la parte de los datos en los que estés interesado. De este modo tu aplicación no tendrá que transferir, analizar y almacenar campos innecesarios y podrá utilizar recursos como la red, la CPU y la memoria con más eficacia.

Existen dos tipos de solicitudes parciales:

  • Respuesta parcial: solicitud donde especificas los campos que se incluirán en la respuesta (utiliza el parámetro de solicitud fields).
  • Parche: solicitud de actualización donde solo se envían los campos que se quieren cambiar (utiliza el verbo HTTP PATCH).

En las siguientes secciones se proporciona más información sobre cómo crear solicitudes parciales.

Respuesta parcial

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

Para solicitar una respuesta parcial, usa el parámetro de solicitud fields a fin de especificar los campos que quieres que se devuelvan. Puedes usar este parámetro con cualquier solicitud que devuelva datos de respuesta.

Ten en cuenta que el parámetro fields solo afecta a los datos de respuesta; no afecta a los datos que necesitas enviar, si los hubiera. Para reducir la cantidad de datos que envías al modificar los recursos, utiliza una solicitud de parche.

Ejemplo

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

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

https://www.googleapis.com/demo/v1?key=YOUR-API-KEY

Respuesta del recurso completo: entre los datos del recurso completo se incluyen los siguientes campos, junto con muchos otros que se han omitido para abreviar.

{
  "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 una respuesta parcial: la solicitud siguiente para este mismo recurso utiliza el parámetro fields a fin de reducir considerablemente la cantidad de datos devueltos.

https://www.googleapis.com/demo/v1?key=YOUR-API-KEY&fields=kind,items(title,characteristics/length)

Respuesta parcial: como respuesta a la solicitud anterior, el servidor devuelve una respuesta que incluye solo el tipo de información junto con una matriz reducida de elementos que contiene únicamente el título HTML y los datos sobre las características de la longitud de cada elemento.

200 OK

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

Ten en cuenta que la respuesta es un objeto JSON que incluye únicamente los campos seleccionados y sus objetos principales contenedores.

A continuación se ofrece información sobre cómo dar formato al parámetro fields, seguida de más datos sobre lo que se devuelve exactamente en la respuesta.

Resumen de la sintaxis del parámetro fields

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 ofrecen ejemplos adicionales en la siguiente sección.

  • Utiliza una lista separada por comas para seleccionar varios campos.
  • Utiliza a/b para seleccionar un campo b anidado en el campo a; utiliza a/b/c para seleccionar un campo c anidado en b.

    Excepción: Para las respuestas de API que usen contenedores "data", donde la respuesta está anidada en un objeto data similar a data: { ... }, no incluyas "data" en la especificación fields. La inclusión del objeto data con una especificación fields como data/a/b provoca un error. En su lugar, utiliza solo una especificación fields como a/b.

  • Utiliza un selector secundario para solicitar un conjunto de campos secundarios específicos incluyendo las expresiones entre paréntesis "( )".

    Por ejemplo: fields=items(id,author/email) solo devuelve el ID del elemento y el correo electrónico del autor para cada elemento de la matriz. También puedes especificar un campo secundario individual, donde fields=items(id) equivale a fields=items/id.

  • Si es necesario, utiliza comodines en las selecciones de campo.

    Por ejemplo: fields=items/pagemap/* selecciona todos los objetos de un pagemap.

Más ejemplos del uso del parámetro fields

En los ejemplos siguientes se incluyen descripciones del modo en que el valor del parámetro fields afecta a la respuesta.

Nota: Al igual que sucede con todos los valores de parámetro de consulta, el valor de parámetro fields debe estar codificado para URL. Para facilitar la legibilidad, en los ejemplos de este documento se omite la codificación.

Identifica los campos que deseas que se devuelvan o realiza selecciones de campo.
El valor de parámetro de solicitud fields es una lista separada por comas de campos y cada campo se especifica relativo a la raíz de la respuesta. De este modo, si realizas una operación list, la respuesta es una colección y, por lo general, incluye una serie de recursos. Si vas realizar una operación que devuelve un solo recurso, los campos se especifican en relación con dicho recurso. Si el campo que seleccionas es una matriz, o parte de ella, el servidor devuelve la parte seleccionada de todos los elementos de la matriz.

A continuación, se ofrecen algunos ejemplos de colección:
Ejemplos Efecto
items Devuelve todos los elementos de la matriz, incluidos todos los campos de cada elemento, pero no el resto de campos.
etag,items Devuelve el campo etag y todos los elementos de la matriz items.
items/title Devuelve solo el campo title de todos los elementos de la matriz ítems.

Siempre que se devuelve un campo anidado, la respuesta incluye los objetos principales contenedores. Los campos principales no incluyen otros campos secundarios, salvo que también se hayan seleccionado de forma explícita.
context/facets/label Devuelve únicamente el campo label para todos los miembros de la matriz facets, que está anidada en el objeto context.
items/pagemap/*/title Por cada elemento de la matriz items, devuelve únicamente el campo title (si está) de todos los objetos secundarios de pagemap.

A continuación, se ofrecen algunos ejemplos de recurso:
Ejemplos Efecto
title Devuelve el campo title del recurso solicitado.
author/uri Devuelve el campo secundario uri del objeto author en el recurso solicitado.
links/*/href
Devuelve el campo href de todos los objetos que son secundarios de links.
Solicita solo partes de campos específicos mediante selecciones secundarias.
De forma predeterminada, si tu solicitud especifica determinados campos, el servidor devuelve los objetos o los elementos de matriz en su totalidad. Puedes especificar una respuesta que incluya únicamente determinados campos secundarios. Puedes hacerlo mediante la sintaxis de selección secundaria "( )", tal como se muestra en el ejemplo siguiente.
Ejemplo Efecto
items(title,author/uri) Devuelve únicamente los valores de title y uri del autor por cada elemento de la matriz items.

Cómo gestionar las respuestas parciales

Después de que un servidor procese una solicitud válida que incluya 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 HTTP 400 Bad Request, junto con un mensaje de error que indica al usuario el error de su selección de fields (por ejemplo, "Invalid field selection a/b").

A continuación, se muestra un ejemplo de respuesta parcial que aparece en la sección de introducción más arriba. En la solicitud se utiliza el parámetro fields para especificar los campos que deben devolverse.

https://www.googleapis.com/demo/v1?key=YOUR-API-KEY&fields=kind,items(title,characteristics/length)

La respuesta parcial tiene el siguiente aspecto:

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), utiliza estos parámetros para reducir los resultados de cada consulta y obtener así un tamaño que se pueda manejar. De lo contrario, podrían no obtenerse los beneficios de rendimiento que se conseguirían con la respuesta parcial.

Parche (actualización parcial)

También puedes evitar el envío de datos innecesarios al modificar los recursos. Para enviar datos solo para determinados campos que estás cambiando, utiliza el verbo PATCH de HTTP. La semántica de parches descrita en este documento es distinta, y más simple, de la utilizada en la implementación anterior de GData de la actualización parcial.

En el breve ejemplo que se ofrece a continuación se muestra cómo el uso de parches minimiza los datos necesarios que se deben enviar para realizar una actualización pequeña.

Ejemplo

En este ejemplo se muestra una solicitud de parche simple para actualizar únicamente el título de un recurso de la API "Demo" genérico (ficticio). El recurso también tiene un comentario, un conjunto de características, un estado y muchos más campos, pero esta solicitud solo envía el campo title, ya que es el único campo que se va a modificar.

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 el código de estado 200 OK, junto con la representación completa del recurso actualizado. Como el campo title se ha incluido en la solicitud de parche, es el único valor que es distinto.

Nota: Si utilizas el parámetro fields de la respuesta parcial en combinación con el parche, puedes aumentar aún más la eficacia de tus 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. Para reducir la cantidad de datos enviados en ambas direcciones, utiliza una solicitud de parche con el parámetro fields.

Semántica de una solicitud de parche

El cuerpo de la solicitud de parche solo incluye los campos de recurso que quieras modificar. Al especificar un campo, debes incluir cualquier objeto principal de inclusión, del mismo modo que los elementos principales de inclusión se devuelven con una respuesta parcial. Los datos modificados que envíes se fusionan con los datos del objeto principal, si hay alguno.The modified data you send is merged into the data for the parent object, if there is one.

  • Agregar: para agregar un campo que no exista todavía, especifícalo junto con su valor.
  • Modificar: para cambiar el valor de un campo, especifícalo y configúralo como el nuevo valor.
  • Suprimir: para suprimir un campo, especifícalo y configúralo como null. Por ejemplo, "comment": null. También puedes suprimir un objeto entero (si es mutable) estableciéndolo en null. Si estás usando la biblioteca de cliente de la API para Java, utiliza en su lugar Data.NULL_STRING. Para obtener más información al respecto, consulta JSON null.

Nota sobre las matrices: las solicitudes de parche que contienen matrices siempre reemplazan a la matriz actual por la que proporciones. No puedes modificar, agregar o suprimir elementos de una matriz de forma gradual.

Usar el parche en un ciclo de lectura-modificación-escritura

Puede ser una práctica útil empezar con la recuperación de una respuesta parcial con los datos que desees modificar. Esto resulta de gran importancia en el caso de los recursos que utilizan ETag, ya que debes proporcionar el valor de ETag actual en el encabezado HTTP If-Match para actualizar el recurso correctamente. Después de obtener los datos, puedes modificar los valores que desees cambiar y enviar la representación parcial modificada con una solicitud de parche. A continuación, te presentamos un ejemplo en el que se supone que el recurso Demo utiliza ETag:

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. Tal 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. */
  }
}

Construir una solicitud de parche dirm

En algunas solicitudes de parche, es necesario basarlas en los datos que se han recuperado anteriormente. Por ejemplo, si quieres agregar un elemento a una matriz y no deseas perder sus elementos, primero debes obtener los datos. Del mismo modo, si una API utiliza ETag, debes enviar el valor de ETag anterior con la solicitud para actualizar el recurso correctamente.

Nota: Puedes utilizar un encabezado HTTP "If-Match: *" para forzar que se realice un parche cuando se usan ETag.  Si lo haces de esta forma, no necesitas la operación de lectura antes de la de escritura.

No obstante, en otras situaciones puedes construir la solicitud de parche directamente, sin recuperar antes los datos. Por ejemplo, puedes configurar una solicitud de parche que actualice un campo con un valor nuevo o que agregue un campo nuevo. A continuación te ofrecemos 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
  }
}

En esta solicitud, si el campo comment tiene un valor, el nuevo valor lo sobrescribe, de lo contrario, lo configura como el nuevo valor. Del mismo modo, si hay una característica volume, su valor se sobrescribe, de lo contrario, se crea. Si se configura el campo accuracy, se elimina.

Gestionar 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 usa ETag, el servidor actualiza los valores de ETag cuando procesa correctamente una solicitud de parche, del mismo modo que con PUT.

La solicitud de parche devuelve la representación completa del recurso, a menos que utilices 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 válido sintáctica o semánticamente, el servidor devuelve el código de estado HTTP 400 Bad Request o 422 Unprecessable Entity, y no se modifica el estado del recurso. por ejemplo, si intentas suprimir el valor de un campo obligatorio, el servidor devuelve un error.

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

Si tu firewall no permite las solicitudes PATCH de HTTP, realiza una solicitud POST de HTTP y configura el encabezado de anulación como PATCH, tal 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ías datos para una solicitud de actualización que utiliza el verbo PUT de HTTP, solo tienes que enviar los campos que son obligatorios u opcionales; si envías valores que configura el servidor, se ignoran. Aunque pudiera parecer otra forma de realizar una actualización parcial, este enfoque tiene limitaciones. En el caso de las actualizaciones que utilizan el verbo PUT de HTTP, la solicitud no se realiza correctamente si no proporcionas los parámetros obligatorios y se borran los datos configurados anteriormente si no proporcionas parámetros opcionales.

Por este motivo, es mucho más seguro utilizar un parche. Solo debes suministrar los datos de los campos que quieras cambiar; los campos que omitas no se borran. La única excepción a esta regla se produce al repetir elementos o matrices: si los omites todos, permanecen iguales; si proporcionas alguno, el conjunto completo se reemplaza por el que has proporcionado.