Neste documento, explicamos como minimizar o impacto de falhas de jobs em pipelines de lote grandes. As falhas de cargas de trabalho grandes têm um impacto maior devido ao tempo e ao dinheiro necessários para se recuperar e corrigir essas falhas. Tentar novamente esses pipelines do zero quando eles falham é caro em termos de tempo e dinheiro.
Para reduzir falhas caras no pipeline em lote, siga as diretrizes desta página. Como não é possível evitar completamente os elementos com falhas e as falhas do pipeline, as técnicas fornecidas se concentram em aumentar a resiliência, reduzir o custo das falhas e facilitar a depuração e a compreensão das falhas quando elas ocorrem.
Para conferir as práticas recomendadas gerais, consulte Práticas recomendadas para pipelines do Dataflow.
Executar experimentos pequenos para trabalhos grandes
Antes de executar um job em lote grande, execute um ou mais jobs menores em um subconjunto do conjunto de dados. Essa técnica pode fornecer uma estimativa de custo e ajudar a encontrar possíveis pontos de falha.
Custo estimado
A execução de experimentos pode fornecer um valor mínimo estimado do custo total do job. Normalmente, o cálculo do custo do job é cost of test job*size(full dataset)/size(test dataset)
. Dependendo do pipeline, o custo pode ser escalonado de forma superlinear ou, com menos frequência, sublinear. No entanto, essa etapa geralmente fornece uma estimativa aproximada do custo do trabalho. Você também pode testar tamanhos diferentes de entradas para ter uma estimativa melhor de como seus custos são dimensionados. Use essas informações para decidir se você vai continuar com o pipeline atual ou reprojetar o pipeline para reduzir custos.
Encontrar pontos de falha
A execução de experimentos pode expor bugs, possíveis pontos de falha ou problemas de configuração e eficiência. Você também pode examinar outras métricas do pipeline, como as seguintes:
- Se o pipeline usar quase toda a memória disponível, ele poderá apresentar exceções de falta de memória (OOM) com carga mais alta ou com registros excepcionalmente grandes. Talvez seja necessário provisionar mais memória para o job final para evitar esses erros de memória insuficiente.
- Se o pipeline tiver quedas na capacidade de processamento, examine os registros para determinar o motivo. Você pode encontrar um elemento travado ou uma parte do conjunto de dados com um desempenho particularmente ruim. É possível processar esses pontos de dados separadamente ou aplicar um tempo limite ao processar elementos. Para mais informações, consulte a seção Tempo limite para registros caros neste documento.
- Se o desempenho do pipeline em uma tarefa no Dataflow for muito pior do que localmente, examine a lógica do pipeline para descobrir o motivo. Por exemplo, se você estiver recebendo a mesma taxa de transferência com oito núcleos no Dataflow que com um núcleo localmente, o job poderá ter um gargalo na contenção de um recurso. Se a performance estiver pior do que o esperado, considere uma ou mais das seguintes opções:
- Faça mais experimentos com diferentes configurações de máquina ou software.
- Teste localmente com vários núcleos ao mesmo tempo.
- Inspecione o código para encontrar possíveis gargalos na implantação em grande escala.
Se o pipeline tiver recomendações do Dataflow, siga-as para melhorar o desempenho.
Usar filas de mensagens inativas para lidar com dados inválidos inesperados
Os pipelines geralmente têm sucesso na maioria dos elementos de entrada, mas falham em um pequeno subconjunto da entrada. Talvez você não detecte esse problema ao realizar pequenos experimentos, porque eles testam apenas um subconjunto da entrada. Por padrão, o Dataflow repete essas tarefas com falha quatro vezes no modo em lote e um número ilimitado de vezes no modo de streaming. No modo em lote, depois de atingir o limite de novas tentativas, todo o job falha. No modo de streaming, ele pode ficar parado indefinidamente.
Em muitos jobs, é possível excluir esses elementos com falha do pipeline e concluir o restante do job usando uma fila de mensagens inativas (fila de mensagens não processadas). A fila de mensagens inativas transmite os registros com falha para uma PCollection
de saída separada, que pode ser gerenciada separadamente da saída principal. Essa configuração permite que você crie uma política para esses registros. Por exemplo, é possível gravá-los no Pub/Sub manualmente, inspecionar e limpar e, em seguida, processar os registros novamente.
Muitas transformações do Apache Beam incluem compatibilidade integrada com filas de mensagens inativas. Em Java, é possível acessá-las com um objeto ErrorHandler
. No Python, é possível acessá-las usando o método with_exception_handling
. Algumas transformações têm maneiras personalizadas de definir filas de mensagens inativas, que podem ser lidas na documentação da transformação. Para mais informações, consulte Usar filas de mensagens inativas para tratamento de erros.
Para determinar se o job atende aos critérios de uma fila de mensagens inativas, consulte a seção Limitações deste documento.
Limitações da fila de mensagens inativas
Nos cenários a seguir, uma fila de mensagens inativas pode não ser útil:
- Falhas completas do ciclo de vida do worker ou do
DoFn
. Se o processamento falhar para todo o worker ou pacote, uma fila de mensagens inativas não vai detectar a falha. Por exemplo, se o pipeline encontrar uma exceção de falta de memória (OOM), todas as tarefas ativas na VM vão falhar e ser tentadas novamente, sem enviar nada para a fila de mensagens inativas. - Combina ou outras agregações. Se o pipeline realizar cálculos que exigem que todos os elementos de entrada estejam presentes e processados como parte do resultado, tenha cuidado ao usar uma fila de mensagens inativas antes dessa etapa. O uso de uma fila de mensagens inativas exclui parte dos dados de entrada do resultado. Adicionar uma fila de mensagens inativas pode trocar a correção pela tolerância a falhas.
- Falhas no caminho da fila de mensagens inativas. Se um elemento falhar ao ser enviado para o coletor da fila de mensagens inativas, todo o pipeline poderá falhar. Para evitar essa falha, mantenha a lógica da fila de mensagens inativas o mais básica possível. É possível adicionar uma etapa de espera (consulte
wait class
) para garantir que a entrada principal seja concluída antes de gravar os elementos da fila de mensagens inativas. Essa configuração pode reduzir o desempenho e atrasar os sinais de erro do pipeline. - Elementos parcialmente transformados. Se você inserir uma fila de mensagens inativas no pipeline, ela poderá gerar o elemento parcialmente transformado e não ter acesso ao elemento original. Como resultado, não é possível limpar o elemento e executar o pipeline novamente. Em vez disso, talvez seja necessário aplicar uma lógica diferente para correlacionar a saída na fila de mensagens inativas ao elemento original ou interpretar e processar o elemento parcialmente transformado. Isso também pode gerar resultados inconsistentes. Por exemplo, se os elementos forem enviados para duas ramificações de um pipeline e cada ramificação enviar elementos que causam exceções para uma fila de mensagens inativas, um único elemento de entrada poderá ser enviado para uma, para outra, para nenhuma ou para ambas as ramificações.
Tempo limite para registros caros
Os pipelines podem parar de responder ao processar um pequeno subconjunto de elementos mais caros ou que atingem uma limitação que causa falta de resposta, como um impasse. Para atenuar esse problema, algumas transformações permitem definir um tempo limite e falhar nos elementos com tempo limite em qualquer DoFn
de código do usuário que encontre esse problema. Por exemplo, você pode usar o método with_exception_handling
do Python. Quando você usa tempos limite com uma fila de mensagens inativas, o pipeline pode continuar processando elementos saudáveis e avançando, e você pode processar os elementos caros separadamente. Essa configuração pode gerar um custo de desempenho.
Para determinar quais operações DoFn
provavelmente exigem um tempo limite, faça pequenos experimentos antes de lançar o pipeline completo.
Ativar o escalonamento automático vertical
Se você não tiver certeza de quanta memória seu job precisa ou achar que ele corre o risco de ficar sem memória, ative o escalonamento automático vertical. Esse recurso ajuda a evitar falhas de OOM quando os pipelines são executados em uma escala maior ou quando encontram elementos excepcionalmente grandes.
Como o escalonamento automático vertical pode aumentar o custo do job e não impede todas as falhas de memória, você ainda precisa resolver problemas de consumo excessivo de memória. O escalonamento automático vertical também requer o Dataflow Prime, que tem limitações adicionais e um modelo de faturamento diferente.
Soluções alternativas para pipelines com falhas
Alguns pipelines são mais propensos a erros. Embora seja melhor resolver a origem desses erros, para reduzir o custo das falhas, considere as seguintes opções.
Materializar resultados intermediários
Os pipelines podem ter uma ou mais transformações particularmente caras que dominam o tempo de execução do pipeline. As falhas do pipeline após essa transformação podem ser particularmente prejudiciais, porque todo o trabalho já concluído é perdido. Para evitar esse cenário, considere gravar PCollections
intermediários gerados por etapas caras em um coletor, como o Cloud Storage. Essa configuração reduz o custo de uma falha. É preciso pesar essa vantagem contra o custo de realizar a gravação extra. É possível usar esse resultado materializado de uma das seguintes maneiras:
- Divida o pipeline original em dois: um que grava o resultado intermediário e outro que o lê.
- Somente em caso de falha no pipeline, leia e simplifique os resultados da origem original e da coleção intermediária materializada.
Para garantir que essas materializações sejam gravadas antes de um processamento adicional, adicione uma etapa de espera (consulte wait class
) antes de qualquer etapa de processamento subsequente.