Como solucionar problemas de latência elevada no app

Em muitos casos, a latência elevada no aplicativo resultará em erros de servidor 5xx. Portanto, convém seguir um conjunto semelhante de etapas de solução de problemas para restringir a causa raiz dos picos de erro e latência, já que as causas de cada um podem ser as mesmas.

Escopo do problema

Primeiro, defina o escopo do problema da forma mais restrita possível coletando informações relevantes. Veja abaixo algumas sugestões de informações que podem ser relevantes.

  • Quais IDs, serviços e versões do aplicativo serão afetados?
  • Quais endpoints específicos no app foram afetados?
  • Isso afetou todos os clientes globalmente ou um subconjunto específico de clientes?
  • Quais são os horários de início e término do incidente? Especifique o fuso horário.
  • Que erros específicos você vê?
  • Qual é o delta de latência observado, que geralmente é especificado como um aumento em um percentil específico? Por exemplo, a latência aumentou em 2 segundos no 90o percentil.
  • Como você avaliou a latência? Em particular, ele foi medido no cliente ou está visível no Cloud Logging e/ou nos dados de latência do Cloud Monitoring fornecidos pela infraestrutura de exibição do App Engine?
  • Quais são as dependências do aplicativo? Algum deles passou por incidentes?
  • Você fez alguma alteração recente no código, configuração ou carga de trabalho que poderia ter acionado esse problema?

Um aplicativo pode ter monitoramento e geração de registros personalizados que você pode usar para restringir ainda mais o escopo do problema além das sugestões acima. Definir o escopo do problema orientará você na provável causa raiz e determinará as próximas etapas de solução de problemas.

Determinar o que falhou

Em seguida, determine qual componente no caminho da solicitação provavelmente causa a latência ou os erros. Os principais componentes no caminho da solicitação são:

Cliente -> Internet -> Google Front End (GFE) -> Infraestrutura de exibição do App Engine -> Instância do aplicativo

Se as informações reunidas na etapa 1 não direcionarem você para a origem da falha, comece analisando a integridade e o desempenho das instâncias do aplicativo.

Uma maneira de determinar se o problema está ou não na instância do aplicativo é analisar os registros de solicitação do App Engine. Geralmente, se você vê erros de código de status HTTP ou latência elevada nesses registros, o problema está relacionado. está na instância que está executando seu aplicativo.

Há um cenário em que erros elevados e latência nos registros de solicitação podem não ser causados pela própria instância do aplicativo: se o número de instâncias do aplicativo não tiver sido escalonado para corresponder aos níveis de tráfego, seu { 101}As instâncias podem estar sobrecarregadas, resultando em erros elevados e latência.

Se você vir erros elevados ou latência no Cloud Monitoring, geralmente é possível concluir que o problema está acima do balanceador de carga, que registra as métricas do App Engine. Na maioria dos casos, isso indica um problema nas instâncias do aplicativo.

No entanto, se você observar uma latência ou erros elevados no monitoramento de métricas, mas não solicitar registros, poderá ser necessária uma investigação mais detalhada. Isso pode indicar uma falha na camada de balanceamento de carga ou que as instâncias estão passando por uma falha tão grave que o balanceador de carga não pode rotear solicitações para elas. Para diferenciar esses casos, consulte os registros de solicitações antes de iniciar o incidente. Se os registros de solicitação mostrarem o aumento da latência antes da falha, isso indica que as instâncias do aplicativo estavam começando a falhar antes que o balanceador de carga interrompesse o roteamento de solicitações para elas.

Cenários que podem causar incidentes

Veja alguns cenários que os usuários encontraram.

Cliente

Como mapear o IP de um cliente para uma região geográfica

O Google resolve o nome do host do aplicativo do App Engine para o GFE mais próximo do cliente, com base no endereço IP do cliente usado na busca DNS. Se o resolvedor de DNS do cliente não estiver usando o protocolo EDNS0, as solicitações do cliente talvez não sejam roteadas para o GFE mais próximo.

Internet

Conectividade fraca com a Internet

Execute o seguinte comando no seu cliente para determinar se o problema é com a conexão ruim à Internet.

$ curl -s -o /dev/null -w '%{time_connect}\n' <hostname>

O valor de time_connect geralmente representa a latência da conexão do cliente com o Google Front End mais próximo. Se essa conexão for lenta, resolva o problema usando traceroute para determinar qual salto na rede causa o atraso.

Você pode executar testes de clientes em diferentes localizações geográficas. As solicitações serão roteadas automaticamente para o data center do Google mais próximo, que varia de acordo com a localização do cliente.

Clientes com baixa largura de banda

O aplicativo pode estar respondendo rapidamente, mas a resposta pode ser desacelerada por gargalos na rede que fazem com que a infraestrutura de exibição do App Engine não envie pacotes pela rede com a rapidez com que eles poderiam ser enviados.

Google Front End

Bloqueio de HTTP/2 de linha

É possível que os clientes HTTP/2 que enviam várias solicitações em paralelo vejam uma latência elevada devido ao bloqueio do início da linha no GFE. A melhor solução é que os clientes façam upgrade para usar o protocolo QUIC.

Terminação SSL para domínios personalizados

O GFE encerra a conexão SSL. É necessário um salto extra para a terminação SSL se você estiver usando um domínio personalizado, em vez de um domínio appspot.com. Isso pode adicionar latência para aplicativos em execução em algumas regiões.

Infraestrutura de exibição do App Engine

Incidente em todo o serviço

O Google postará detalhes de um serviço grave em todo o serviço em https://status.cloud.google.com/. Observe que o Google faz o lançamento gradualmente para que um incidente de serviço não afete todas as instâncias de uma só vez.

Escalonamento automático

Como escalonar o tráfego muito rapidamente

O escalonamento automático do App Engine pode não escalonar suas instâncias tão rápido quanto o tráfego aumenta, levando a uma sobrecarga temporária. Normalmente, isso ocorre quando o tráfego não é gerado organicamente pelos usuários finais, mas é gerado por um programa de computador. A melhor maneira de resolver é limitar o sistema que gera o tráfego.

Picos no tráfego

Picos no tráfego podem causar latência elevada nos casos em que um aplicativo com escalonamento automático precisa escalonar mais rápido do que é possível sem afetar a latência. O tráfego de usuário final geralmente não causa picos de tráfego frequentes. Se você vir isso, investigue o que está causando os picos de tráfego. Se um sistema em lote estiver sendo executado em intervalos, será possível suavizar o tráfego ou usar diferentes configurações de escalonamento.

Configurações do escalonador automático

O escalonador automático pode ser configurado com base nas características de escalonamento do aplicativo. Esses parâmetros de escalonamento podem não ser ideais durante determinados cenários.

Os aplicativos do ambiente flexível do App Engine são escalonados com base na utilização da CPU. No entanto, o aplicativo pode ficar vinculado à E/S durante um incidente, o que resulta em sobrecarga das instâncias com um alto número de solicitações. Isso acontece porque não ocorre escalonamento baseado em CPU.

As configurações de escalonamento do ambiente padrão do App Engine podem causar latência se forem definidas de forma muito agressiva. Se você vir 500 respostas de servidor com a mensagem Request was aborted after waiting too long to attempt to service your request nos registros, isso significa que a solicitação expirou na fila pendente aguardando uma instância inativa.

Não use o escalonamento manual do ambiente padrão do App Engine se o aplicativo veicular o tráfego de usuários finais. O escalonamento manual é melhor para cargas de trabalho como filas de tarefas. Talvez você veja um tempo pendente maior com escalonamento manual mesmo quando provisionou instâncias suficientes.

Não use o escalonamento básico do ambiente padrão do App Engine para aplicativos sensíveis à latência. Esse tipo de escalonamento foi projetado para minimizar os custos à custa da latência.

As configurações de escalonamento padrão do ambiente padrão do App Engine fornecem a latência ideal para a maioria dos aplicativos. Se você ainda vir solicitações com tempo pendente alto, especifique um número mínimo de instâncias. Ao ajustar as configurações de escalonamento para reduzir os custos minimizando as instâncias inativas, você corre o risco de observar picos de latência se a carga aumentar repentinamente.

Recomendamos que você compare o desempenho com as configurações de escalonamento padrão e, em seguida, execute um novo comparativo de mercado depois de cada alteração nessas configurações.

Implantações

A latência elevada logo após uma implantação indica que você não fez o escalonamento suficiente antes de migrar o tráfego. É possível que as instâncias mais recentes não tenham armazenado caches locais e, portanto, sejam exibidas mais lentamente do que as mais antigas.

Para evitar picos de latência, não implante um aplicativo do App Engine usando o mesmo nome de versão de uma versão existente do aplicativo. Se você reutilizar um nome de versão atual, não será possível migrar lentamente o tráfego para a nova versão. As solicitações podem ficar mais lentas porque todas as instâncias serão reiniciadas em um curto período de tempo. Você também precisará reimplantar se quiser reverter para a versão anterior.

Instância de aplicativo

Código do aplicativo

Problemas no código do aplicativo podem ser muito difíceis de depurar, especialmente se eles forem intermitentes ou não forem facilmente reproduzidos. Para ajudar a diagnosticar problemas, recomendamos que seu aplicativo seja instrumentado com geração de registros, monitoramento e rastreamento , Use o Cloud Profiler para diagnosticar problemas. Veja este exemplo de diagnóstico de latência na solicitação de carregamento por meio do Cloud Trace para fazer upload de informações de tempo adicionais para cada solicitação.

Você também pode tentar reproduzir o problema em um ambiente de desenvolvimento local que pode permitir a execução de ferramentas de depuração específicas da linguagem que talvez não possam ser executadas no App Engine.

Se você estiver executando no ambiente flexível do App Engine, poderá aplicar SSH a uma instância e fazer um despejo de linhas de execução para ver o estado atual do aplicativo. É possível tentar reproduzir o problema em um teste de carga ou executando o aplicativo localmente. É possível aumentar o tamanho da instância para ver se isso resolve o problema. Por exemplo, o aumento da RAM pode resolver problemas de aplicativos que estão enfrentando atrasos devido à coleta de lixo.

Para entender melhor como o app falha e quais gargalos ocorrem, é possível carregá-lo até a falha. Defina uma contagem máxima de instâncias e aumente gradualmente a carga até que o aplicativo falhe.

Se o problema de latência estiver correlacionado à implantação de uma nova versão do código do aplicativo, será possível reverter para determinar se a nova versão causou o incidente. Se você implantar continuamente, poderá ter implantações suficientes com frequência em que é difícil determinar se a implantação causou o incidente com base no tempo de início.

Seu aplicativo pode armazenar as configurações no Datastore ou em outro lugar. Isso será útil se você puder criar um cronograma de alterações de configuração para determinar se algum deles está alinhado com o início da latência elevada.

Alteração na carga de trabalho

Uma alteração na carga de trabalho pode causar uma latência elevada. Algumas métricas de monitoramento que podem indicar a alteração da carga de trabalho incluem o qps, bem como o uso ou a latência da API. Também é possível verificar se há alterações nos tamanhos da solicitação e da resposta.

Falhas na verificação de integridade

O balanceador de carga do ambiente flexível do App Engine interromperá o roteamento de solicitações para instâncias que falharem nas verificações de integridade. Isso pode aumentar a carga em outras instâncias, possivelmente resultando em uma falha em cascata. Os registros Nginx flexíveis do App Engine mostram instâncias que falham nas verificações de integridade. Analise seus registros e monitoramento para determinar por que a instância não está íntegra ou configure as verificações de integridade para serem menos sensíveis a falhas temporárias. Observe que haverá um pequeno atraso até que o balanceador de carga pare de rotear o tráfego para uma instância não íntegra. Esse atraso pode causar um pico de erro se o balanceador de carga não puder repetir solicitações.

O ambiente padrão do App Engine não usa verificações de integridade.

Pressão da memória

Se o monitoramento mostrar um padrão dentário no uso da memória ou uma queda no uso da memória correlacionada às implantações, os problemas de desempenho poderão ser causados por um vazamento de memória. Um vazamento de memória pode causar uma coleta de lixo frequente que leva a uma latência maior. O provisionamento de instâncias maiores com mais memória pode resolver o problema se não for possível rastreá-lo facilmente em um problema no código.

Vazamento de recursos

Se uma instância do aplicativo mostrar uma latência crescente relacionada à idade da instância, é possível que haja um vazamento de recursos que cause problemas de desempenho. Nesse tipo de problema, você também verá quedas de latência logo após uma implantação. Por exemplo, uma estrutura de dados que fica mais lenta ao longo do tempo devido ao uso maior da CPU pode fazer com que qualquer carga de trabalho vinculada à CPU fique mais lenta.

Otimização de código

Veja algumas maneiras de otimizar o código no App Engine para reduzir a latência:

  • Trabalho off-line: use o Cloud Tasks para que as solicitações de usuários não bloqueiem a espera da conclusão do trabalho, como o envio de e-mails.

  • Chamadas de API assíncronas: verifique se o código não está bloqueado aguardando a conclusão da chamada. Bibliotecas como o ndb oferecem suporte integrado para isso.

  • Chamadas de API em lote: a versão em lote de chamadas de API geralmente é mais rápida que o envio de chamadas individuais.

  • Desnormalizar modelos de dados: reduza a latência das chamadas feitas para a camada de persistência de dados desnormalizando seus modelos de dados.

Dependências

É possível monitorar as dependências do aplicativo para detectar se os picos de latência estão relacionados a uma falha de dependência.

Um aumento na latência de uma dependência pode ser causado por uma alteração na carga de trabalho e também por um aumento no tráfego.

Dependência sem escalonamento

Se a dependência não for escalonada conforme o número de instâncias do App Engine for escalonado, a dependência poderá ficar sobrecarregada quando o tráfego aumentar. Um exemplo de uma dependência que pode não ser escalonada é um banco de dados SQL. Um número maior de instâncias de aplicativo levará a um número maior de conexões de banco de dados, o que pode causar falha em cascata impedindo que o banco de dados seja iniciado.

Uma maneira de se recuperar disso é a seguinte:

  1. Implantar uma nova versão padrão que não se conecte ao banco de dados.
  2. Encerre a versão padrão anterior.
  3. Implantar uma nova versão não padrão que se conecte ao banco de dados.
  4. Migre lentamente o tráfego para a nova versão.

Uma medida preventiva possível é projetar seu aplicativo para eliminar solicitações para a dependência usando a limitação adaptável.

Falha na camada de armazenamento em cache

Uma boa maneira de acelerar solicitações é usar várias camadas de armazenamento em cache:

  • Armazenamento em cache próximo dos usuários finais
  • Memcache
  • Memória na instância

Um aumento repentino na latência pode ser causado por uma falha em uma dessas camadas de armazenamento em cache. Por exemplo, um flush do Memcache pode levar mais solicitações para o Datastore mais lento.