O Cloud Tasks permite enviar grandes volumes de tarefas assíncronas enquanto controla a taxa em que o tráfego chega às filas e aos serviços downstream. Ao aplicar padrões de aumento gradual e controles de taxa, é possível escalonar as cargas de trabalho sem problemas, sem acionar picos de latência de fila ou sobrecarga de destino quando o tráfego aumenta mais rápido do que a infraestrutura pode se adaptar.
Visão geral
Este documento fornece diretrizes sobre as práticas recomendadas para manter o alto
desempenho do Cloud Tasks em filas de alto tráfego. Uma fila de alta TPS é uma fila que tem 500 tarefas criadas ou enviadas por segundo (TPS) ou mais. Um grupo de filas de alto TPS é um conjunto contíguo de filas, por exemplo,
[queue0001, queue0002, …, queue0099], que tem pelo menos 2.000 tarefas
criadas ou enviadas por segundo no total. É possível conferir o histórico de TPS de uma
fila ou grupo de filas usando as
métricas do Cloud Monitoring,
api/request_count para operações CreateTask e queue/task_attempt_count
para tentativas de tarefa. As filas e os grupos de filas com alto tráfego estão sujeitos a duas
classes amplas de falhas:
A sobrecarga de fila ocorre quando a criação e o envio de tarefas para uma fila ou um grupo de filas individual aumenta mais rápido do que a infraestrutura de fila pode se adaptar. A infraestrutura do Google usa camadas adaptáveis que realocam dinamicamente a carga com base nos padrões de tráfego, e essa adaptação leva tempo. Da mesma forma, a sobrecarga de destino ocorre quando a taxa de envio de tarefas causa picos de tráfego na infraestrutura de destino downstream. Em ambos os casos, siga um padrão 500/50/5: ao escalonar além de 500 TPS, aumente o tráfego em no máximo 50% a cada 5 minutos.
Diferente do padrão 500/50/5 para cargas de trabalho de TPS alto, a aceleração inicial da fila afeta todas as filas quando elas começam em um estado frio ou inativo, incluindo filas configuradas para taxas de envio moderadas. Neste documento, analisamos diferentes cenários que podem introduzir riscos de escalonamento e fornecemos exemplos de como gerenciar o aumento da fila e aplicar o padrão 500/50/5.
Aumento inicial da fila
O padrão 500/50/5 se aplica a filas de TPS alto que já operam em um estado estável. A aceleração inicial da fila é um mecanismo de sistema separado que se aplica a todas as filas, incluindo aquelas configuradas para taxas de envio moderadas, como 20 a 100 TPS, à medida que elas fazem a transição de um estado frio ou inativo para uma operação em estado estável.
Uma fila entra em um estado frio ou inativo em qualquer uma das seguintes situações:
A fila foi criada recentemente ou retomada após uma pausa.
A fila ficou inativa por alguns minutos sem envios ativos.
A fila está se recuperando após o recuo das respostas de erro HTTP
429ou5xxdownstream. Para mais informações sobre como o backoff de erro afeta as taxas de envio, consulte Erros de backoff e taxas aplicadas.
Quando as tarefas chegam a uma fila fria ou inativa, o Cloud Tasks não as envia imediatamente na taxa max_dispatches_per_second configurada. Para proteger os destinos downstream contra picos repentinos de tráfego,
o Cloud Tasks começa a enviar a uma taxa de referência baixa, como
cerca de 1 TPS. Em seguida, ela aumenta progressivamente a taxa de envio aplicada em intervalos de avaliação periódicos. A taxa aplicada continua aumentando enquanto
a demanda da fila permanece saturada e os gerenciadores de destino retornam respostas
HTTP 2xx. Dependendo da taxa de destino, pode levar vários minutos para alcançar valores altos de max_dispatches_per_second.
Se a carga de trabalho enviar tráfego com picos separados por breves períodos de inatividade de alguns minutos ou mais, a fila será redefinida para um estado frio entre as intermitências e repetirá esse processo de aumento em cada intermitência. Para minimizar os atrasos de aumento gradual em cargas de trabalho sensíveis a picos, siga estas práticas recomendadas:
Mantenha um fluxo constante de tráfego de referência para manter as filas sensíveis à latência ativas entre as intermitências.
Reutilize as filas atuais em vez de excluí-las e recriá-las com frequência.
Provisione capacidade de destino downstream suficiente para que os gerenciadores retornem respostas HTTP
2xxe evitem retornar respostas de erro HTTP429ou5xxque redefinam a taxa de envio aplicada.
Diagnosticar limitação de fila
Se a fila enviar tarefas mais lentamente do que a taxa
max_dispatches_per_second
configurada, verifique se o gargalo vem do aumento da fila fria ou inativa,
da espera por congestionamento de destino ou dos limites de simultaneidade.
Aumento de fila fria ou inativa
A causa provável é o aumento inicial da fila se todas as seguintes condições se aplicarem:
- A fila foi criada recentemente, retomada depois de ser pausada ou ficou inativa por alguns minutos antes da chegada do tráfego.
- As tentativas de tarefa são bem-sucedidas sem erros de destino, mostrando
response_code="OK"na métrica do Monitoringcloudtasks.googleapis.com/queue/task_attempt_count. - Os envios em andamento permanecem abaixo de
max_concurrent_dispatches, enquantocloudtasks.googleapis.com/queue/depthoucloudtasks.googleapis.com/queue/task_attempt_delaysé elevado. Ao mesmo tempo, a taxa de envio emcloudtasks.googleapis.com/queue/task_attempt_countaumenta progressivamente em intervalos de avaliação periódicos.
Para mais informações sobre as métricas do Monitoring, consulte Enviar métricas para o Monitoring.
Sobrecarga de destino e espera de congestionamento
O Cloud Tasks reduz dinamicamente as taxas de envio se o destino
retornar respostas de erro HTTP 429 Too Many Requests ou HTTP 5xx, como
HTTP 503 Service Unavailable. Esse recuo de congestionamento evita a sobrecarga do destino.
Para verificar se os erros de destino estão fazendo com que o Cloud Tasks
limite os envios, confira a métrica do Monitoring
cloudtasks.googleapis.com/queue/task_attempt_count agrupada pelo
rótulo response_code. Se a geração de registros de fila estiver ativada, também será possível inspecionar os
registros de resposta de tentativa na Análise de Registros:
resource.type="cloud_tasks_queue"
jsonPayload.attemptResponseLog.status!="OK"
Em response_code e jsonPayload.attemptResponseLog.status,
o Cloud Tasks registra códigos de status gRPC canônicos em vez de
códigos de status HTTP numéricos. Por exemplo, HTTP 429 é mapeado para
RESOURCE_EXHAUSTED, HTTP 503 é mapeado para UNAVAILABLE, HTTP 500 é mapeado para
INTERNAL e HTTP 504 ou um tempo limite é mapeado para DEADLINE_EXCEEDED.
Se você observar RESOURCE_EXHAUSTED, UNAVAILABLE ou outros status de erro de servidor
do destino, escalonar verticalmente as instâncias de serviço de destino ou a
simultaneidade de destino antes de aumentar os limites de envio da fila.
Para mais informações sobre como ativar os registros de fila, consulte Usar o Cloud Logging com filas.
Gargalo de simultaneidade
De acordo com a lei de Little, a latência de destino downstream limita a capacidade máxima de envio:
Max Throughput (tasks/sec) = min(
max_dispatches_per_second,
max_concurrent_dispatches / Downstream Latency in seconds
)
Por exemplo, se a latência de execução downstream for de 2 segundos e
max_concurrent_dispatches estiver definido como 100,
a capacidade será limitada a 50 tarefas por segundo, mesmo que
max_dispatches_per_second esteja configurado como
500.
Para diagnosticar se a simultaneidade é o gargalo, divida
max_concurrent_dispatches pela latência de resposta
de destino registrada no campo
jsonPayload.attemptResponseLog.attemptDuration no
Logging. Compare esse limite calculado com a taxa de envio real na métrica do Monitoring cloudtasks.googleapis.com/queue/task_attempt_count. Se as distribuições reais
estabilizarem perto desse limite enquanto cloudtasks.googleapis.com/queue/depth ou
cloudtasks.googleapis.com/queue/task_attempt_delays crescerem, realize uma das
seguintes ações:
- Se o destino downstream tiver capacidade extra, como quando as tarefas passam a maior parte
da duração aguardando a E/S externa, aumente
max_concurrent_dispatches. - Se o destino downstream já estiver com alta utilização de recursos,
aumentar
max_concurrent_dispatchespode piorar a sobrecarga do destino. Em vez disso, escalonar horizontalmente as instâncias de destino ou reduza a latência de execução do gerenciador.
sobrecarga da fila
As filas ou os grupos de filas podem ficar sobrecarregados sempre que o tráfego aumenta repentinamente. Como resultado, essas filas podem apresentar:
- aumento da latência da criação de tarefas;
- aumento da taxa de erros na criação de tarefas;
- redução na taxa de despacho.
Para se defender contra isso, estabeleça controles em qualquer situação em que a taxa de criação ou envio de uma fila ou grupo de filas possa aumentar repentinamente. Comece com um máximo de 500 operações por segundo em uma fila ou grupo de filas frio e, em seguida, aumente o tráfego em 50% a cada 5 minutos. Em teoria, é possível chegar a 740 mil operações por segundo após 90 minutos usando essa programação de aumento gradual. Há várias circunstâncias em que isso pode ocorrer.
Exemplo:
- lançamento de novos recursos que fazem uso intenso do Cloud Tasks
- movimentação do tráfego entre filas
- reequilíbrio do tráfego em mais ou menos filas
- execução de jobs em lote que injetam um grande número de tarefas
Nesses e em outros casos, siga o padrão 500/50/5.
Usar a divisão de tráfego do App Engine
Se um aplicativo do App Engine criar as tarefas, use a divisão de tráfego do App Engine (ambiente padrão do App Engine ou ambiente flexível do App Engine) para suavizar os aumentos de tráfego. Ao dividir o tráfego entre as versões (ambiente padrão ou ambiente flexível), é possível aumentar as solicitações gerenciadas por taxa ao longo do tempo para proteger a integridade da fila. Por exemplo, considere o caso de aumento do tráfego para um grupo de filas recém-expandido: deixe [queue0000, queue0199] ser uma sequência de filas de alto TPS que recebem 100.000 criações de TPS no total no pico.
Deixe [queue0200, queue0399] ser uma sequência de novas filas. Depois de mudar todo o tráfego, o número de filas na sequência dobra, e o novo intervalo de filas recebe 50% do tráfego total da sequência.
Ao implantar a versão que aumenta o número de filas, aumente gradualmente o tráfego para a nova versão e, portanto, para as novas filas, usando a divisão de tráfego:
- Comece movendo 1% do tráfego para a nova versão. Por exemplo, 50% de 1% de 100.000 TPS gera 500 TPS para o conjunto de novas filas.
- A cada cinco minutos, aumente em 50% o tráfego enviado para a nova versão, conforme detalhado na tabela a seguir:
| Minutos desde o início da implantação | % do tráfego total deslocado para a nova versão | % do tráfego total para as novas filas | % do tráfego total para as filas antigas |
|---|---|---|---|
| 0 | 1.0 | 0,5 | 99,5 |
| 5 | 1,5 | 0,75 | 99,25 |
| 10 | 2,3 | 1,15 | 98,85 |
| 15 | 3,4 | 1,7 | 98,3 |
| 20 | 5,1 | 2,55 | 97,45 |
| 25 | 7,6 | 3,8 | 96,2 |
| 30 | 11,4 | 5,7 | 94,3 |
| 35 | 17,1 | 8,55 | 91,45 |
| 40 | 25,6 | 12,8 | 87,2 |
| 45 | 38,4 | 19,2 | 80,8 |
| 50 | 57,7 | 28,85 | 71,15 |
| 55 | 86,5 | 43,25 | 56,75 |
| 60 | 100 | 50 | 50 |
Picos de tráfego impulsionados pela versão
Ao lançar uma versão que aumenta significativamente o tráfego para uma fila ou grupo de filas, o lançamento gradual é, novamente, um mecanismo importante para suavizar os aumentos. Lance as instâncias gradualmente para que o lançamento inicial não exceda 500 operações por segundo no total para as novas filas, aumentando em no máximo 50% a cada 5 minutos.
Novas filas ou grupos de filas com alto TPS
Filas recém-criadas são especialmente vulneráveis. Grupos de filas, por exemplo, [queue0000, queue0001, …, queue0199], são tão sensíveis quanto filas únicas durante os estágios iniciais de lançamento. Para essas filas, o lançamento gradual é uma estratégia importante. Lance serviços novos ou atualizados que criem filas ou grupos de filas com alto TPS em etapas. Mantenha a carga inicial abaixo de 500 TPS e aumente em 50% ou menos, com pelo menos 5 minutos de intervalo.
Grupos de filas recém-expandidos
Ao aumentar a capacidade total de um grupo de filas, por exemplo, expandindo [queue0000-queue0199 para queue0000-queue0399], siga o padrão 500/50/5. Para procedimentos de lançamento, os novos grupos de filas se comportam da mesma forma que as filas individuais. Aplique o padrão 500/50/5 ao novo grupo como um todo, não apenas a filas individuais dentro do grupo.
Para essas expansões de grupos de filas, o lançamento gradual é uma estratégia importante. Se a origem do tráfego for o App Engine, use a divisão de tráfego. Ao migrar o serviço para adicionar tarefas ao número maior de filas, lance as instâncias gradualmente para que o lançamento inicial não exceda 500 operações no total para as novas filas e não aumente o tráfego em mais de 50% a cada 5 minutos.
Expansão emergencial do grupo de filas
Às vezes, talvez você queira expandir um grupo de filas atual, por exemplo, porque espera que as tarefas sejam adicionadas ao grupo de filas mais rapidamente do que o grupo pode enviá-las. Se você distribuir os nomes das novas filas de maneira uniforme entre os nomes das filas atuais em ordem lexicográfica, poderá enviar tráfego imediatamente para essas filas. Verifique se não há mais de 50% de novas filas intercaladas e se o tráfego para cada fila é menor que 500 TPS. Esse método é uma alternativa ao uso da divisão de tráfego e do lançamento gradual.
Para conseguir esse tipo de nomenclatura intercalada, adicione um sufixo às filas que terminam em números pares. Por exemplo, se você tiver 200 filas [queue0000-queue0199] e quiser criar 100 novas filas, escolha [queue0000a, queue0002a, queue0004a, …, queue0198a] como os novos nomes de fila, em vez de [queue0200-queue0299].
Se você precisar de um aumento maior, ainda será possível intercalar até 50% mais filas a cada 5 minutos.
Enfileiramento de tarefas em lote ou em grande escala
Quando você precisa adicionar um grande número de tarefas, por exemplo, milhões ou bilhões, um padrão de injeção dupla pode ser útil. Em vez de criar tarefas de um único job, use uma fila de injetores. Cada tarefa adicionada à fila do injetor se divide e adiciona 100 tarefas à fila ou ao grupo de filas relevante. É possível acelerar a fila do injetor ao longo do tempo. Por exemplo, comece com 5 TPS para gerar 500 TPS na fila ou no grupo de filas de destino e, em seguida, aumente a taxa em 50% a cada 5 minutos.
Tarefas nomeadas
Quando você cria uma tarefa, o Cloud Tasks atribui a ela um nome exclusivo
por padrão. É possível atribuir seu próprio nome a uma tarefa usando o parâmetro name. No entanto, isso apresenta uma sobrecarga de desempenho significativa, resultando em maiores latências e taxas de erro potencialmente maiores associadas a tarefas nomeadas. Nomes de tarefas sequenciais, como carimbos de data/hora, podem aumentar significativamente essa sobrecarga.
Se você atribuir seus próprios nomes, use um prefixo bem distribuído para nomes de tarefas, como
um hash do conteúdo. Para mais informações sobre como nomear uma tarefa, consulte a
referência do campo Task.name.
sobrecarga do destino
O Cloud Tasks pode sobrecarregar os serviços e recursos downstream que você usa, como o App Engine, o Firestore no modo Datastore (Datastore) e sua rede, se os envios de fila aumentarem repentinamente. Se houver um acúmulo de tarefas, retomar essas filas pode sobrecarregar os serviços. Para se defender contra a sobrecarga de destino, siga o padrão 500/50/5: se uma fila enviar mais de 500 TPS, aumente o tráfego acionado por uma fila em no máximo 50% a cada 5 minutos. Para monitorar os aumentos de tráfego de forma proativa, use as métricas do Monitoring. É possível usar os alertas do Monitoring para detectar situações potencialmente perigosas.
Retomar filas de alta TPS
Quando você retoma uma fila pausada, o Cloud Tasks aplica a
inicialização da fila e aumenta gradualmente a taxa de envio de
um valor de referência baixo para a taxa
max_dispatches_per_second
configurada da fila. No entanto, se um grande backlog de tarefas se acumular em uma fila de alto TPS ou
em várias filas que você retomar ao mesmo tempo, a taxa de envio ainda poderá
subir mais rápido do que os serviços de destino downstream podem escalonar. Para evitar a sobrecarga do destino ao retomar filas com um grande backlog, escalone a retomada de várias filas. Como alternativa, reduza temporariamente a taxa de
max_dispatches_per_second
e aumente-a gradualmente seguindo o padrão 500/50/5. Para mais
informações sobre como o Cloud Tasks limita e aumenta
os envios quando as filas são retomadas, consulte Erros de espera e taxas
aplicadas.
Tarefas agendadas em massa
Um grande número de tarefas programadas para serem enviadas ao mesmo tempo também pode introduzir um risco de sobrecarga do destino. Se você precisar iniciar um grande número de tarefas de uma só vez, use os controles de taxa de fila para aumentar gradualmente a taxa de envio ou provisionar a capacidade de destino com antecedência.
Maior fan-out
Ao atualizar os serviços que o Cloud Tasks chama, aumentar o número de chamadas remotas pode criar riscos de produção. Por exemplo, digamos que as tarefas
em uma fila de TPS alto chamem o gerenciador /task-foo. Uma nova versão pode
aumentar significativamente o custo de chamar /task-foo se, por exemplo, essa nova
versão adicionar várias chamadas caras do Datastore ao gerenciador.
O resultado líquido de uma versão como essa é um aumento enorme no tráfego do Datastore, que está imediatamente relacionado a mudanças no tráfego do usuário. Use o lançamento gradual ou a divisão de tráfego para gerenciar o aumento.
Novas tentativas
Seu código pode tentar novamente em caso de falha ao fazer chamadas da API Cloud Tasks. No entanto, quando uma proporção significativa de solicitações falha com erros do lado do servidor, uma alta taxa de repetição pode sobrecarregar ainda mais as filas e retardar a recuperação. Limite a quantidade de tráfego de saída se o cliente detectar que uma proporção significativa de solicitações está falhando com erros do lado do servidor. Por exemplo, é possível usar o algoritmo de limitação adaptativa descrito no capítulo Como lidar com sobrecarga do livro Engenharia de confiabilidade do site. As bibliotecas de cliente gRPC do Google implementam uma variação desse algoritmo.