Dicas de desempenho

Neste documento, há algumas técnicas que você pode usar para melhorar o desempenho do seu aplicativo. Em alguns casos, são usados exemplos de outras APIs ou de APIs genéricas para ilustrar as ideias apresentadas. No entanto, os mesmos conceitos são aplicáveis à Google Cloud Deployment Manager V2 API.

Usar gzip

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

Para receber uma resposta codificada com gzip, faça duas coisas: defina um cabeçalho Accept-Encoding e modifique seu agente de usuário para conter a string gzip. Veja um exemplo de cabeçalhos HTTP formados devidamente para permitir a compactação gzip:

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

Trabalhar com recursos parciais

Outra forma de melhorar o desempenho das chamadas de API é enviar e receber apenas a parte dos dados do seu interesse. Assim, evitam-se a transferência, a análise e o armazenamento de campos desnecessários no aplicativo para que os recursos sejam usados de maneira mais eficiente, inclusive rede, CPU e memória.

Há dois tipos de solicitações parciais:

  • Resposta parcial: uma solicitação para especificar os campos a incluir na resposta. Use o parâmetro de solicitação fields.
  • Patch: uma solicitação de atualização para enviar apenas os campos que você deseja alterar. Use o verbo HTTP PATCH.

Nas seções a seguir, há mais detalhes sobre como fazer solicitações parciais.

Resposta parcial

Por padrão, depois de processar as solicitações, o servidor envia de volta a representação completa de um recurso. Para alcançar mais desempenho, solicite ao servidor o envio apenas dos campos realmente necessários para receber somente uma resposta parcial.

Para solicitar uma resposta parcial, use o parâmetro de solicitação fields para especificar os campos a ser retornados. Use esse parâmetro com qualquer solicitação que retorne dados de resposta.

Observe que o parâmetro fields só afeta os dados de resposta, e não os de envio, se houver. Para reduzir a quantidade de dados enviados durante a modificação de recursos, use uma solicitação de patch.

Exemplo

O exemplo a seguir mostra o uso do parâmetro fields com uma "Demo" API 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?key=YOUR-API-KEY

Resposta de recursos completos: os dados de recursos completos incluem os seguintes campos, além de muitos outros omitidos para agilizar o processo.

{
  "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 uma resposta parcial: a seguinte solicitação para este mesmo recurso usa o parâmetro fields para reduzir significativamente a quantidade de dados retornados.

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

Resposta parcial: em reação à solicitação acima, o servidor envia de volta uma resposta que contém somente as informações de tipo, além de uma matriz de itens pareados com características de tamanho e título 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 contém apenas os campos selecionados e os respectivos objetos pai.

Os detalhes sobre como formatar o parâmetro fields são abordados a seguir, com informações sobre o que exatamente é retornado na resposta.

Resumo da sintaxe do parâmetro fields

O formato do parâmetro de solicitação fields baseia-se vagamente na sintaxe XPath. A sintaxe compatível é resumida abaixo, e exemplos adicionais são fornecidos nesta seção:

  • Use uma lista separada por vírgula para selecionar vários campos.
  • Use a/b para selecionar um campo b aninhado dentro do campo a, e a/b/c para um campo c dentro de b.

    Exceção: para respostas de API que usam envoltórios de "dados", cuja resposta é aninhada dentro de um objeto data que se parece com data: { ... }, não inclua "data" na especificação de fields. A inclusão do objeto de dados com uma especificação de fields como data/a/b causa erro. Portanto, use apenas uma especificação fields como a/b.

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

    Por exemplo: fields=items(id,author/email) retorna apenas o código do item e o e-mail do autor para cada elemento na matriz de itens. Também é possível especificar um único subcampo, em que fields=items(id) é equivalente a fields=items/id.

  • Se necessário, use caracteres curinga em seleções de campo.

    Por exemplo: fields=items/pagemap/* seleciona todos os objetos em um pagemap.

Mais exemplos do uso do parâmetro fields

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

Observação: assim como em todos os valores de parâmetros de consulta, o valor do parâmetro fields precisa ter codificação de URL. Para facilitar a leitura, os exemplos neste documento estão sem a codificação.

Identifique os campos a ser retornados 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 um é especificado em relação à raiz da resposta. Portanto, se você está executando uma operação de lista, a resposta é uma coleção e, geralmente, inclui uma matriz de recursos. Se você está executando uma operação que retorna um único recurso, os campos são especificados em relação a esse recurso. Se o campo selecionado é uma matriz, ou parte dela, o servidor retorna a parte selecionada de todos os elementos na matriz.

Veja alguns exemplos com base na coleção:
Exemplos Efeito
items Retorna todos os elementos na matriz de itens, inclusive todos os campos de cada elemento, mas não outros campos.
etag,items Retorna o campo etag e todos os elementos na matriz de itens.
items/title Retorna somente o campo title para todos os elementos na matriz de itens.

Sempre que um campo aninhado é retornado, a resposta inclui os respectivos objetos pai. Os campos pai não incluem outros campos filho, a menos que também sejam explicitamente selecionados.
context/facets/label Retorna apenas o campo label para todos os membros da matriz facets, que é aninhada sob o objeto context.
items/pagemap/*/title Para cada elemento da matriz de itens, a coleção retorna apenas o campo title, se presente, de todos os objetos filho de pagemap.

Veja alguns exemplos com base no 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 filho de links.
Solicite apenas partes de campos específicos usando subseleções.
Por padrão, se há campos particulares especificados na solicitação, todos os objetos ou elementos da matriz são retornados no servidor. Defina uma resposta que inclua apenas alguns subcampos. Para isso, use a sintaxe de subseleção "( )", como no exemplo abaixo.
Exemplo Efeito
items(title,author/uri) Retorna somente os valores de title e o uri do autor para cada elemento na matriz de itens.

Processar 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 com os dados solicitados. Se o parâmetro de consulta fields tem um erro ou é inválido, o servidor retorna um código de status HTTP 400 Bad Request com uma mensagem de erro informando ao usuário o que havia de errado com a seleção de campos. Por exemplo, "Invalid field selection a/b".

Veja o exemplo da resposta parcial mostrada na seção introdutória acima. Na solicitação, é usado o parâmetro fields para especificar os campos a ser retornados.

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

A resposta parcial é parecida com esta:

200 OK

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

Observação: em APIs compatíveis com parâmetros de consulta para paginação de dados, por exemplo maxResults e nextPageToken, use esses parâmetros para reduzir os resultados de cada consulta a um tamanho administrável. Caso contrário, os possíveis ganhos de desempenho talvez não se concretizem.

Patch (atualização parcial)

Evite também o envio de dados desnecessários ao modificar recursos. Para enviar dados atualizados apenas em relação aos campos específicos que estão sendo alterados, use o verbo HTTP PATCH. A semântica de patch descrita neste documento é diferente e mais simples do que a implementação mais antiga de GData de atualização parcial.

O breve exemplo abaixo mostra como o uso de patch reduz a quantidade de dados que você precisa enviar ao fazer uma pequena atualização.

Exemplo

Neste exemplo, há uma solicitação simples de patch para atualizar apenas o título do recurso de uma "Demo" API genérica (fictícia). O recurso também tem um comentário, um conjunto de características, um status e muitos outros campos, mas esta solicitação envia apenas o campo title, pois é o único 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 com a representação completa do recurso atualizado. Como foi incluído apenas o campo title na solicitação de patch, esse é o único valor diferente em relação à implementação anterior.

Observação: se você usa o parâmetro fields de resposta parcial em conjunto com o patch, aumente ainda mais a eficiência das suas solicitações de atualização. Uma solicitação de patch só 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 recurso a ser modificados. Ao especificar um campo, você precisa incluir os objetos pai, da mesma forma como esses objetos são retornados com uma resposta parcial. Os dados modificados que você envia são incorporados aos do objeto pai, se houver um.

  • Adicionar: para adicionar um campo que ainda não existe, especifique o novo campo e o valor dele.
  • Modificar: para alterar o valor de um campo existente, especifique e configure-o com o novo valor.
  • Excluir: para excluir um campo, especifique e configure-o como null. Por exemplo, "comment": null. Para excluir também um objeto inteiro, se ele permitir alteração, configure-o como null. Se você estiver usando a Biblioteca cliente de APIs para Java, em vez dela, use Data.NULL_STRING. Para mais detalhes, consulte JSON null.

Observação sobre matrizes: solicitações de patch que contêm matrizes substituem a matriz já existente por uma fornecida por você. Não modifique, adicione nem exclua itens de uma matriz de maneira fragmentada.

Usar patch em um ciclo ler-modificar-gravar

Pode ser uma prática útil começar recuperando uma resposta parcial com os dados que você deseja modificar. Isso é especialmente importante para recursos que usam ETag, pois é necessário fornecer o valor atual dela no cabeçalho HTTP If-Match para atualizar o recurso. Depois de receber os dados, você pode modificar os valores a ser alterados e enviar de volta a representação parcial modificada com uma solicitação de patch. Veja um exemplo em que o recurso Demo supostamente 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 seguinte solicitação de patch baseia-se nessa resposta. Conforme mostrado abaixo, ela também usa o parâmetro fields para limitar os dados retornados na resposta de 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. */
  }
}

Construir diretamente uma solicitação de patch

Para algumas solicitações de patch, fundamente-as de acordo com os dados recuperados anteriormente. Por exemplo, se você deseja adicionar um item a uma matriz sem perder nenhum dos elementos dela, primeiro é necessário receber os dados existentes. Da mesma forma, se uma API usa ETags, envie o valor anterior da ETag com a solicitação para atualizar o recurso.

Observação: use um cabeçalho HTTP "If-Match: *" para forçar a passagem de um patch quando ETags estão em uso.  Se isso é feito, não é necessário ler antes de gravar.

No entanto, em outras circunstâncias, construa a solicitação de patch diretamente, sem recuperar primeiro os dados existentes. Por exemplo, você pode configurar facilmente uma solicitação de patch que atualiza um campo para um novo valor ou que adiciona um novo campo. Veja 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 essa solicitação, se o campo de comentário tem um valor existente, o novo valor o substitui. Caso contrário, ele é definido com o novo valor. Da mesma forma, se houvesse uma característica de volume, o valor dele seria substituído. Do contrário, seria criado. O campo de precisão, se definido, é removido.

Processar resposta para um patch

Depois de processar uma solicitação válida de patch, a API retorna um código de resposta HTTP 200 OK com a representação completa do recurso modificado. Se a API usa ETags, o servidor atualiza os valores delas ao processar uma solicitação de patch, como acontece com PUT.

A solicitação de patch retorna a representação completa do recurso, a não ser que você use o parâmetro fields para reduzir a quantidade de dados retornados.

Se uma solicitação de patch gera um novo estado de recurso sintática ou semanticamente inválido, o servidor retorna um código de status HTTP 400 Bad Request ou 422 Unprocessable Entity e o estado permanece inalterado. Por exemplo, se você tenta excluir o valor de um campo obrigatório, o servidor retorna um erro.

Notação alternativa quando o verbo HTTP PATCH não é compatível

Se não são permitidas solicitações HTTP PATCH pelo firewall, 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, quando você envia dados para uma solicitação de atualização que usa o verbo HTTP PUT, só é necessário enviar os campos obrigatórios ou opcionais. Se você envia valores referentes a campos definidos pelo servidor, eles são ignorados. Embora essa pareça ser outra forma de fazer uma atualização parcial, a abordagem tem algumas limitações. Com atualizações que usam o verbo HTTP PUT, a solicitação falha quando não são fornecidos parâmetros obrigatórios, além de remover dados já definidos quando parâmetros opcionais não são informados.

Por esse motivo, é muito mais seguro usar um patch. Só forneça dados referentes aos campos que deseja alterar. Os campos omitidos não são removidos. A única exceção a essa regra ocorre com elementos repetidos ou matrizes. Se você os omite, eles ficam como estão. Se fornece parte deles, o conjunto inteiro é substituído pelo conjunto fornecido.