Práticas recomendadas para pipelines de processamento em massa grandes

Este documento explica como minimizar o impacto das falhas de tarefas para pipelines de processamento em lote grandes. As falhas de carga de trabalho grandes são particularmente impactantes devido ao tempo e ao dinheiro necessários para recuperar e corrigir estas falhas. Voltar a tentar estas condutas desde o início quando falham é dispendioso em termos de tempo e dinheiro.

Para reduzir as falhas dispendiosas da pipeline de processamento em lote, siga as diretrizes nesta página. Uma vez que nem sempre pode evitar completamente os elementos com falhas e as falhas de pipeline, as técnicas fornecidas focam-se no aumento da capacidade de recuperação, na redução do custo das falhas e na facilitação da depuração e da compreensão das falhas quando ocorrem.

Para ver as práticas recomendadas gerais de pipelines, consulte o artigo Práticas recomendadas de pipelines do Dataflow.

Execute pequenas experiências para grandes tarefas

Antes de executar uma tarefa em lote grande, execute uma ou mais tarefas mais pequenas num subconjunto do conjunto de dados. Esta técnica pode fornecer uma estimativa de custos e ajudar a encontrar potenciais pontos de falha.

Estimativa de custos

A execução de experiências pode fornecer um limite mínimo estimado do custo total de execução da tarefa. Normalmente, o cálculo do custo do trabalho é cost of test job*size(full dataset)/size(test dataset). Consoante o pipeline, o custo pode ser superlinear ou, menos frequentemente, sublinear. No entanto, este passo oferece frequentemente uma boa estimativa aproximada do custo do trabalho. Também pode experimentar diferentes tamanhos de entradas para obter uma melhor estimativa de como os seus custos são dimensionados. Use estas informações para decidir se quer continuar com o pipeline existente ou reestruturar o pipeline para reduzir os custos.

Encontre pontos de falha

A execução de experiências pode expor erros, potenciais pontos de falha ou potenciais problemas de configuração e eficiência. Também pode examinar outras métricas do pipeline, como as seguintes:

  • Se o seu pipeline usar quase toda a memória disponível, pode ter exceções de falta de memória (OOM) sob uma carga mais elevada ou com registos excecionalmente grandes. Pode ter de aprovisionar mais memória para a tarefa final para evitar estes erros de falta de memória.
  • Se o seu pipeline registar diminuições no débito, examine os registos do pipeline para determinar o motivo. Pode encontrar um elemento bloqueado ou uma parte do conjunto de dados com um desempenho particularmente fraco. Pode processar estes pontos de dados separadamente ou aplicar um limite de tempo ao processar elementos. Para mais informações, consulte a secção Limite o tempo de espera de registos dispendiosos neste documento.
  • Se o seu pipeline tiver um desempenho muito pior numa tarefa no Dataflow do que localmente, examine a lógica do pipeline para descobrir o motivo. Por exemplo, se estiver a obter o mesmo débito com oito núcleos no Dataflow que com um núcleo localmente, o trabalho pode estar limitado pela contenção de um recurso. Se verificar que o desempenho é pior do que o esperado, considere uma ou mais das seguintes opções:
    • Execute mais experiências com diferentes configurações de software ou máquinas.
    • Teste localmente com vários núcleos em simultâneo.
    • Inspeccione o seu código para encontrar potenciais gargalos na implementação em grande escala.

Se o seu pipeline tiver recomendações do Dataflow, siga-as para melhorar o desempenho.

Use filas de mensagens rejeitadas para processar dados incorretos inesperados

Muitas vezes, os pipelines têm êxito na maioria dos elementos de entrada, mas falham num pequeno subconjunto da entrada. Pode não detetar este problema quando executa experiências pequenas, porque estas experiências apenas testam um subconjunto da entrada. Por predefinição, o Dataflow tenta novamente estas tarefas com falhas quatro vezes no modo de lote e um número ilimitado de vezes no modo de streaming. No modo de lote, após atingir o limite de novas tentativas, toda a tarefa falha. No modo de streaming, pode ficar parado indefinidamente.

Em muitas tarefas, pode excluir estes elementos com falhas do pipeline e concluir o resto da tarefa usando uma fila de mensagens rejeitadas (fila de mensagens não processadas). A fila de mensagens rejeitadas passa os registos com falhas para um resultado separado PCollection, que pode gerir separadamente do resultado principal. Esta configuração permite-lhe criar uma política para estes registos. Por exemplo, pode escrevê-los manualmente no Pub/Sub, inspecioná-los e limpá-los e, em seguida, processar novamente os registos.

Muitas transformações do Apache Beam incluem suporte incorporado para filas de mensagens rejeitadas. Em Java, pode aceder a eles com um objeto ErrorHandler. Em Python, pode aceder a estes elementos através do método with_exception_handling. Algumas transformações têm formas personalizadas de definir filas de mensagens rejeitadas, que pode consultar na documentação da transformação. Para mais informações, consulte o artigo Use filas de mensagens rejeitadas para o processamento de erros.

Para determinar se a sua tarefa cumpre os critérios para uma fila de mensagens rejeitadas, consulte a secção Limitações neste documento.

Limitações da fila de mensagens não entregues

Nos seguintes cenários, uma fila de mensagens rejeitadas pode não ser útil:

  • Falhas do ciclo de vida do trabalhador completo ou DoFn. Se o processamento falhar para todo o trabalhador ou pacote, uma fila de mensagens rejeitadas não consegue detetar a falha. Por exemplo, se o seu pipeline encontrar uma exceção de falta de memória (OOM), todas as tarefas ativas na VM falham e são repetidas, sem enviar nada para a fila de mensagens rejeitadas.
  • Combinações ou outras agregações. Se o seu pipeline realizar cálculos que exigem que todos os elementos de entrada estejam presentes e sejam processados como parte do resultado, tenha cuidado ao usar uma fila de mensagens rejeitadas antes deste passo. A utilização de uma fila de mensagens rejeitadas exclui parte dos dados de entrada do resultado. Adicionar uma fila de mensagens rejeitadas pode trocar a correção pela tolerância a falhas.
  • Falhas no caminho da fila de mensagens rejeitadas. Se um elemento falhar durante o envio para o destino da fila de mensagens rejeitadas, todo o pipeline pode falhar. Para evitar esta falha, mantenha a lógica da fila de mensagens rejeitadas o mais básica possível. Pode adicionar um passo de espera (consulte wait class) para garantir que a entrada principal termina antes de escrever os elementos da fila de mensagens rejeitadas. Esta configuração pode reduzir o desempenho e atrasar os sinais de erro da sua conduta.
  • Elementos parcialmente transformados. Se inserir uma fila de mensagens rejeitadas a meio do pipeline, a fila de mensagens rejeitadas pode gerar o elemento parcialmente transformado e não ter acesso ao elemento original. Como resultado, não pode limpar o elemento e voltar a executar o pipeline contra o mesmo. Em alternativa, pode ter de aplicar uma lógica diferente para correlacionar a saída na fila de mensagens rejeitadas com o elemento original ou pode ter de interpretar e processar o elemento parcialmente transformado. Também pode resultar em resultados inconsistentes. Por exemplo, se os elementos forem enviados por dois ramos de um pipeline e cada ramo enviar elementos que causam exceções para uma fila de mensagens rejeitadas, um único elemento de entrada pode chegar a um, ao outro, a ambos ou a nenhum dos ramos.

Exceda o tempo limite de registos dispendiosos

Os pipelines podem deixar de responder enquanto processam um pequeno subconjunto de elementos mais caros ou que atingem uma limitação que causa falta de resposta, como um impasse. Para mitigar este problema, algumas transformações permitem definir um limite de tempo e falhar os elementos com limite de tempo excedido em quaisquer DoFns de código do utilizador que encontrem este problema. Por exemplo, pode usar o método with_exception_handling do Python. Quando usa limites de tempo com uma fila de mensagens rejeitadas, o pipeline pode continuar a processar elementos válidos e progredir, e pode voltar a processar os elementos dispendiosos separadamente. Esta configuração pode incorrer num custo de desempenho.

Para determinar que operações têm probabilidade de exigir um limite de tempo, execute pequenas experiências antes de lançar o pipeline completo.DoFn

Ative o ajuste de escala automático vertical

Se não tiver a certeza da quantidade de memória de que o seu trabalho precisa ou achar que o seu trabalho corre o risco de ficar sem memória, ative o dimensionamento automático vertical. Esta funcionalidade ajuda a evitar falhas de OOM quando os pipelines são executados em maior escala ou quando encontram elementos excecionalmente grandes.

Uma vez que o ajuste automático vertical pode aumentar o custo da sua tarefa e não impede todas as falhas de falta de memória, continua a ter de resolver os problemas de consumo excessivo de memória. O dimensionamento automático vertical também requer o Dataflow Prime, que tem limitações adicionais e um modelo de faturação diferente.

Soluções alternativas para pipelines propensos a falhas

Alguns pipelines são particularmente propensos a erros. Embora seja melhor resolver a origem destes erros, para reduzir o custo das falhas, considere as seguintes opções.

Materialize resultados intermédios

Os pipelines podem ter uma ou mais transformações particularmente caras que dominam o tempo de execução do pipeline. As falhas de pipeline após esta transformação podem ser particularmente prejudiciais, porque todo o trabalho já concluído é perdido. Para evitar este cenário, considere escrever os PCollections intermediários gerados por passos dispendiosos num destino, como o Cloud Storage. Esta configuração reduz o custo de uma falha. Tem de ponderar esta vantagem em relação ao custo de realizar a escrita adicional. Pode usar este resultado materializado de uma das seguintes formas:

  1. Divida o pipeline original em dois pipelines: um que escreve o resultado intermédio e outro que o lê.
  2. Apenas em caso de falha do pipeline, leia e reduza os resultados da sua origem original e da sua coleção intermédia materializada.

Para garantir que estas materializações são escritas antes do processamento adicional, adicione um passo de espera (consulte wait class) antes de quaisquer passos de processamento subsequentes.