Melhore o desempenho

Este documento aborda algumas técnicas que você pode usar para melhorar o desempenho do seu aplicativo. Em alguns casos, exemplos de outras APIs ou APIs genéricas são usados ​​para ilustrar as ideias apresentadas. No entanto, os mesmos conceitos se aplicam à API Compute Engine.

Compactação usando gzip

Uma maneira fácil e conveniente de reduzir a largura de banda necessária para cada solicitação é habilitar a compactação gzip. Embora isso exija tempo adicional de CPU para descompactar os resultados, a compensação com os custos de rede geralmente faz com que valha a pena.

Para receber uma resposta codificada em gzip, você deve fazer duas coisas: definir um cabeçalho Accept-Encoding e modificar seu agente de usuário para conter a string gzip . Aqui está um exemplo de cabeçalhos HTTP formados corretamente para ativar a compactação gzip:

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

Trabalhando com recursos parciais

Outra maneira de melhorar o desempenho de suas chamadas de API é enviar e receber apenas a parte dos dados de seu interesse. Isso permite que seu aplicativo evite transferir, analisar e armazenar campos desnecessários, para que possa usar recursos, incluindo rede, CPU e memória, com mais eficiência.

Existem dois tipos de solicitações parciais:

  • Resposta parcial : uma solicitação onde você especifica quais campos incluir na resposta (use o parâmetro de solicitação fields ).
  • Patch : Uma solicitação de atualização onde você envia apenas os campos que deseja alterar (use o verbo PATCH HTTP).

Mais detalhes sobre como fazer solicitações parciais são fornecidos nas seções a seguir.

Resposta parcial

Por padrão, o servidor envia de volta a representação completa de um recurso após processar as solicitações. Para melhor desempenho, você pode solicitar ao servidor que envie apenas os campos realmente necessários e, em vez disso, obtenha uma resposta parcial .

Para solicitar uma resposta parcial, use o parâmetro de solicitação fields para especificar os campos que você deseja retornar. Você pode usar esse parâmetro com qualquer solicitação que retorne dados de resposta.

Observe que o parâmetro fields afeta apenas os dados de resposta; isso não afeta os dados que você precisa enviar, se houver. Para reduzir a quantidade de dados enviados ao modificar recursos, use uma solicitação de patch .

Exemplo

O exemplo a seguir mostra o uso do parâmetro fields com uma API "Demo" genérica (fictícia).

Solicitação simples: esta solicitação HTTP GET omite o parâmetro fields e retorna o recurso completo.

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

Resposta completa do recurso: os dados completos do recurso incluem os campos a seguir, juntamente com muitos outros que foram omitidos por questões de brevidade.

{
  "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",
    ...
  },
  ...
  ]
}

Solicitação de resposta parcial: A solicitação a seguir para esse mesmo recurso usa o parâmetro fields para reduzir significativamente a quantidade de dados retornados.

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

Resposta parcial: em resposta à solicitação acima, o servidor envia de volta uma resposta que contém apenas as informações de tipo junto com uma matriz de itens reduzida que inclui apenas informações de características de título e comprimento HTML em cada item.

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

Observe que a resposta é um objeto JSON que inclui apenas os campos selecionados e seus objetos pai envolventes.

Detalhes sobre como formatar o parâmetro fields são abordados a seguir, seguidos de mais detalhes sobre o que exatamente é retornado na resposta.

Resumo da sintaxe dos parâmetros dos campos

O formato do valor do parâmetro de solicitação fields é vagamente baseado na sintaxe XPath. A sintaxe suportada está resumida abaixo e exemplos adicionais são fornecidos na seção a seguir.

  • Use uma lista separada por vírgulas para selecionar vários campos.
  • Use a/b para selecionar um campo b que esteja aninhado no campo a ; use a/b/c para selecionar um campo c aninhado em b .

    Exceção: para respostas de API que usam wrappers "data", onde a resposta está aninhada em um objeto data que se parece com data: { ... } , não inclua " data " na especificação fields . Incluir o objeto de dados com uma especificação de campos como data/a/b causa um erro. Em vez disso, basta usar uma especificação fields como a/b .

  • Utilize um subseletor para solicitar um conjunto de subcampos específicos de arrays ou objetos colocando expressões entre parênteses " ( ) ".

    Por exemplo: fields=items(id,author/email) retorna apenas o ID do item e o email do autor para cada elemento na matriz de itens. Você também pode especificar um único subcampo, onde fields=items(id) é equivalente a fields=items/id .

  • Use curingas nas seleções de campo, se necessário.

    Por exemplo: fields=items/pagemap/* seleciona todos os objetos em um mapa de páginas.

Mais exemplos de uso do parâmetro campos

Os exemplos abaixo incluem descrições de como o valor do parâmetro fields afeta a resposta.

Nota: Tal como acontece com todos os valores de parâmetros de consulta, o valor do parâmetro fields deve ser codificado em URL. Para melhor legibilidade, os exemplos neste documento omitem a codificação.

Identifique os campos que você deseja retornar ou faça seleções de campos .
O valor do parâmetro de solicitação fields é uma lista de campos separados por vírgula e cada campo é especificado em relação à raiz da resposta. Assim, se você estiver executando uma operação de lista , a resposta será uma coleção e geralmente inclui uma matriz de recursos. Se você estiver executando uma operação que retorna um único recurso, os campos serão especificados em relação a esse recurso. Se o campo selecionado for (ou fizer parte de) um array, o servidor retornará a parte selecionada de todos os elementos do array.

Aqui estão alguns exemplos em nível de coleção:
Exemplos Efeito
items Retorna todos os elementos da matriz de itens, incluindo todos os campos de cada elemento, mas nenhum outro campo.
etag,items Retorna o campo etag e todos os elementos da matriz de itens.
items/title Retorna apenas o campo title para todos os elementos da matriz de itens.

Sempre que um campo aninhado é retornado, a resposta inclui os objetos pai envolventes. Os campos pai não incluem nenhum outro campo filho, a menos que também sejam selecionados explicitamente.
context/facets/label Retorna apenas o campo label para todos os membros da matriz facets , que está aninhada no objeto context .
items/pagemap/*/title Para cada elemento do array items, retorna apenas o campo title (se presente) de todos os objetos que são filhos de pagemap .

Aqui estão alguns exemplos em nível de recurso:
Exemplos Efeito
title Retorna o campo title do recurso solicitado.
author/uri Retorna o subcampo uri do objeto author no recurso solicitado.
links/*/href
Retorna o campo href de todos os objetos filhos de links .
Solicite apenas partes de campos específicos usando subseleções .
Por padrão, se sua solicitação especificar campos específicos, o servidor retornará os objetos ou elementos do array em sua totalidade. Você pode especificar uma resposta que inclua apenas determinados subcampos. Você faz isso usando a sintaxe de subseleção " ( ) ", como no exemplo abaixo.
Exemplo Efeito
items(title,author/uri) Retorna apenas os valores do title e uri do autor para cada elemento da matriz de itens.

Lidando com respostas parciais

Depois que um servidor processa uma solicitação válida que inclui o parâmetro de consulta fields , ele envia de volta um código de status HTTP 200 OK , juntamente com os dados solicitados. Se o parâmetro de consulta fields apresentar um erro ou for inválido, o servidor retornará um código de status HTTP 400 Bad Request , junto com uma mensagem de erro informando ao usuário o que havia de errado com sua seleção de campos (por exemplo, "Invalid field selection a/b" ).

Aqui está o exemplo de resposta parcial mostrado na seção introdutória acima. A solicitação usa o parâmetro fields para especificar quais campos retornar.

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

A resposta parcial é assim:

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

Observação: para APIs que suportam parâmetros de consulta para paginação de dados ( maxResults e nextPageToken , por exemplo), use esses parâmetros para reduzir os resultados de cada consulta a um tamanho gerenciável. Caso contrário, os ganhos de desempenho possíveis com resposta parcial poderão não ser alcançados.

Patch (atualização parcial)

Você também pode evitar o envio de dados desnecessários ao modificar recursos. Para enviar dados atualizados apenas para os campos específicos que você está alterando, use o verbo HTTP PATCH . A semântica do patch descrita neste documento é diferente (e mais simples) do que era para a implementação de atualização parcial do GData mais antiga.

O breve exemplo abaixo mostra como o uso do patch minimiza os dados que você precisa enviar para fazer uma pequena atualização.

Exemplo

Este exemplo mostra uma solicitação de patch simples para atualizar apenas o título de um recurso de API "Demo" genérico (fictício). O recurso também possui um comentário, um conjunto de características, status e muitos outros campos, mas esta solicitação envia apenas o campo title , pois é o único campo que está sendo modificado:

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

{
  "title": "New title"
}

Resposta:

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

O servidor retorna um código de status 200 OK , juntamente com a representação completa do recurso atualizado. Como apenas o campo title foi incluído na solicitação de patch, esse é o único valor diferente de antes.

Observação: se você usar o parâmetro fields de resposta parcial em combinação com patch, poderá aumentar ainda mais a eficiência de suas solicitações de atualização. Uma solicitação de patch apenas reduz o tamanho da solicitação. Uma resposta parcial reduz o tamanho da resposta. Portanto, para reduzir a quantidade de dados enviados nas duas direções, use uma solicitação de patch com o parâmetro fields .

Semântica de uma solicitação de patch

O corpo da solicitação de patch inclui apenas os campos de recursos que você deseja modificar. Ao especificar um campo, você deve incluir todos os objetos pai envolventes, assim como os pais envolventes são retornados com uma resposta parcial . Os dados modificados que você envia são mesclados nos dados do objeto pai, se houver.

  • Adicionar: para adicionar um campo que ainda não existe, especifique o novo campo e seu valor.
  • Modificar: para alterar o valor de um campo existente, especifique o campo e defina-o com o novo valor.
  • Excluir: para excluir um campo, especifique o campo e defina-o como null . Por exemplo, "comment": null . Você também pode excluir um objeto inteiro (se for mutável) definindo-o como null . Se você estiver usando a Java API Client Library , use Data.NULL_STRING ; para obter detalhes, consulte JSON null .

Observação sobre matrizes: solicitações de patch que contêm matrizes substituem a matriz existente por aquela que você fornece. Você não pode modificar, adicionar ou excluir itens de uma matriz de maneira fragmentada.

Usando patch em um ciclo de leitura-modificação-gravação

Pode ser uma prática útil começar recuperando uma resposta parcial com os dados que você deseja modificar. Isto é especialmente importante para recursos que usam ETags, pois você deve fornecer o valor ETag atual no cabeçalho HTTP If-Match para atualizar o recurso com êxito. Depois de obter os dados, você poderá modificar os valores que deseja alterar e enviar de volta a representação parcial modificada com uma solicitação de patch. Aqui está um exemplo que pressupõe que o recurso Demo usa ETags:

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

Esta é a resposta parcial:

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

A solicitação de patch a seguir é baseada nessa resposta. Conforme mostrado abaixo, ele também usa o parâmetro fields para limitar os dados retornados na resposta do patch:

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

O servidor responde com um código de status HTTP 200 OK e a representação parcial do recurso atualizado:

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

Construindo uma solicitação de patch diretamente

Para algumas solicitações de patch, você precisa baseá-las nos dados recuperados anteriormente. Por exemplo, se você quiser adicionar um item a uma matriz e não quiser perder nenhum dos elementos existentes da matriz, deverá primeiro obter os dados existentes. Da mesma forma, se uma API usar ETags, você precisará enviar o valor ETag anterior com sua solicitação para atualizar o recurso com sucesso.

Nota: Você pode usar um cabeçalho HTTP "If-Match: *" para forçar a passagem de um patch quando ETags estiverem em uso. Se você fizer isso, não precisará ler antes de escrever.

Para outras situações, entretanto, você pode construir a solicitação de patch diretamente, sem primeiro recuperar os dados existentes. Por exemplo, você pode configurar facilmente uma solicitação de patch que atualize um campo para um novo valor ou adicione um novo campo. Aqui está um exemplo:

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

Com esta solicitação, se o campo de comentário tiver um valor existente, o novo valor o substituirá; caso contrário, será definido com o novo valor. Da mesma forma, se houver uma característica de volume, seu valor será sobrescrito; se não, ele é criado. O campo de precisão, se definido, é removido.

Lidando com a resposta a um patch

Depois de processar uma solicitação de patch válida, a API retorna um código de resposta HTTP 200 OK junto com a representação completa do recurso modificado. Se ETags forem usados ​​pela API, o servidor atualizará os valores de ETag quando processar com êxito uma solicitação de patch, assim como faz com PUT .

A solicitação de patch retorna toda a representação do recurso, a menos que você use o parâmetro fields para reduzir a quantidade de dados retornada.

Se uma solicitação de patch resultar em um novo estado de recurso que seja sintaticamente ou semanticamente inválido, o servidor retornará um código de status HTTP 400 Bad Request ou 422 Unprocessable Entity e o estado do recurso permanecerá inalterado. Por exemplo, se você tentar excluir o valor de um campo obrigatório, o servidor retornará um erro.

Notação alternativa quando o verbo PATCH HTTP não é suportado

Se o seu firewall não permitir solicitações HTTP PATCH , faça uma solicitação HTTP POST e defina o cabeçalho de substituição como PATCH , conforme mostrado abaixo:

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

Diferença entre patch e atualização

Na prática, ao enviar dados para uma solicitação de atualização que usa o verbo HTTP PUT , você só precisa enviar os campos obrigatórios ou opcionais; se você enviar valores para campos definidos pelo servidor, eles serão ignorados. Embora possa parecer outra maneira de fazer uma atualização parcial, esta abordagem tem algumas limitações. Com atualizações que usam o verbo HTTP PUT , a solicitação falhará se você não fornecer os parâmetros necessários e limpará os dados definidos anteriormente se você não fornecer parâmetros opcionais.

É muito mais seguro usar patch por esse motivo. Você fornece dados apenas para os campos que deseja alterar; os campos omitidos não serão desmarcados. A única exceção a esta regra ocorre com elementos ou matrizes repetidas: se você omitir todos eles, eles permanecerão como estão; se você fornecer algum deles, todo o conjunto será substituído pelo conjunto que você fornecer.