En este documento se explica cómo minimizar el impacto de los errores de los trabajos en las grandes canalizaciones por lotes. Los fallos en cargas de trabajo grandes son especialmente perjudiciales debido al tiempo y al dinero que se necesitan para recuperarse de ellos y solucionarlos. Volver a intentar estas canalizaciones desde cero cuando fallan es caro en términos de tiempo y dinero.
Para reducir los errores costosos de las canalizaciones de procesamiento por lotes, sigue las directrices de esta página. Como no siempre puedes evitar por completo los errores en los elementos y en las canalizaciones, las técnicas que se proporcionan se centran en aumentar la resiliencia, reducir el coste de los errores y facilitar la depuración y la comprensión de los errores cuando se producen.
Para consultar las prácticas recomendadas generales de las canalizaciones, consulta Prácticas recomendadas de las canalizaciones de Dataflow.
Realizar experimentos pequeños para tareas grandes
Antes de ejecutar una tarea por lotes grande, ejecuta una o varias tareas más pequeñas en un subconjunto del conjunto de datos. Esta técnica puede proporcionar una estimación de costes y ayudar a encontrar posibles puntos de fallo.
Estimación de costes
Al ejecutar experimentos, se puede obtener un precio mínimo estimado del coste total de la tarea. Normalmente, el cálculo del coste del trabajo es cost of test
job*size(full dataset)/size(test dataset). En función de la canalización, el coste puede aumentar de forma superlineal o, con menos frecuencia, de forma sublineal. Sin embargo, este paso suele proporcionar una buena estimación aproximada del coste del trabajo. También puedes probar con diferentes tamaños de entradas para obtener una estimación más precisa de cómo se escalan tus costes. Usa esta información para decidir si quieres continuar con la canalización actual o rediseñarla para reducir costes.
Encontrar puntos de fallo
Al realizar experimentos, se pueden detectar errores, posibles puntos de fallo o posibles problemas de configuración y eficiencia. También puede examinar otras métricas de la canalización, como las siguientes:
- Si tu canalización usa casi toda la memoria disponible, puede que se produzcan excepciones de falta de memoria (OOM) cuando la carga sea mayor o cuando los registros sean excepcionalmente grandes. Puede que tengas que aprovisionar más memoria para el trabajo final y evitar estos errores de falta de memoria.
- Si tu flujo de procesamiento experimenta descensos en el rendimiento, examina los registros del flujo para determinar el motivo. Puede que encuentres un elemento atascado o una parte de tu conjunto de datos con un rendimiento especialmente bajo. Puedes procesar estos puntos de datos por separado o aplicar un tiempo de espera al procesar elementos. Para obtener más información, consulta la sección Tiempo de espera de registros caros de este documento.
- Si tu flujo de procesamiento tiene un rendimiento mucho peor en una tarea en Dataflow que de forma local, examina la lógica del flujo para averiguar por qué. Por ejemplo, si obtienes el mismo rendimiento con ocho núcleos en Dataflow que con un núcleo de forma local, es posible que el trabajo esté limitado por la contención de un recurso. Si observas que el rendimiento es inferior al esperado, puedes probar una o varias de las siguientes opciones:
- Realiza más experimentos con diferentes configuraciones de software o de máquina.
- Prueba de forma local con varios núcleos al mismo tiempo.
- Inspecciona el código para detectar posibles cuellos de botella al implementar a gran escala.
Si tu flujo de procesamiento tiene alguna recomendación de Dataflow, síguela para mejorar el rendimiento.
Usar colas de mensajes fallidos para gestionar datos incorrectos inesperados
Los pipelines suelen funcionar correctamente en la mayoría de los elementos de entrada, pero fallan en un pequeño subconjunto de la entrada. Es posible que no detectes este problema cuando ejecutes experimentos pequeños, ya que estos experimentos solo prueban un subconjunto de la entrada. De forma predeterminada, Dataflow vuelve a intentar ejecutar estas tareas fallidas cuatro veces en el modo por lotes y un número ilimitado de veces en el modo de streaming. En el modo por lotes, si se alcanza el límite de reintentos, toda la tarea fallará. En el modo de streaming, puede detenerse indefinidamente.
En muchos trabajos, puedes excluir estos elementos fallidos de la canalización y completar el resto del trabajo mediante una cola de mensajes fallidos (cola de mensajes no procesados). La cola de mensajes fallidos envía los registros fallidos a una salida independiente
PCollection, que puedes gestionar por separado de la salida principal. Esta configuración te permite diseñar una política para estos registros. Por ejemplo, puedes escribir los registros en Pub/Sub manualmente, inspeccionarlos y limpiarlos, y, a continuación, volver a procesarlos.
Muchas transformaciones de Apache Beam incluyen compatibilidad integrada con colas de mensajes fallidos.
En Java, puedes acceder a ellos con un objeto ErrorHandler. En Python, puedes acceder a ellos mediante el método with_exception_handling. Algunas transformaciones tienen formas personalizadas de definir colas de mensajes fallidos, que puedes consultar en la documentación de la transformación. Para obtener más información, consulta Usar colas de mensajes fallidos para gestionar errores.
Para determinar si tu trabajo cumple los criterios de una cola de mensajes fallidos, consulta la sección Limitaciones de este documento.
Limitaciones de las colas de mensajes fallidos
En los siguientes casos, una cola de mensajes fallidos puede no ser útil:
- Errores en el ciclo de vida completo del trabajador o de
DoFn. Si falla el procesamiento de todo el trabajador o paquete, una cola de mensajes fallidos no puede detectar el error. Por ejemplo, si tu canal se encuentra con una excepción de falta de memoria (OOM), todas las tareas activas de la máquina virtual fallarán y se volverán a intentar, sin enviar nada a la cola de mensajes fallidos. - Combinaciones u otras agregaciones. Si tu canalización realiza cálculos que requieren que todos los elementos de entrada estén presentes y se procesen como parte del resultado, ten cuidado al usar una cola de mensajes fallidos antes de este paso. Si usas una cola de mensajes fallidos, se excluirá parte de los datos de entrada del resultado. Si añades una cola de mensajes fallidos, puede que sacrifiques la corrección por la tolerancia a fallos.
- Errores en la ruta de la cola de mensajes fallidos. Si un elemento falla mientras se envía al receptor de la cola de mensajes fallidos, puede fallar toda la canalización.
Para evitar este error, mantén la lógica de la cola de mensajes fallidos lo más básica posible. Puedes añadir un paso de espera (consulta la
wait class) para asegurarte de que la entrada principal finalice antes de escribir los elementos de la cola de mensajes fallidos. Esta configuración puede reducir el rendimiento y retrasar las señales de error de tu canal. - Elementos transformados parcialmente. Si insertas una cola de mensajes fallidos en mitad de tu canalización, es posible que la cola de mensajes fallidos genere el elemento parcialmente transformado y no tenga acceso al elemento original. Por lo tanto, no puedes limpiar el elemento y volver a ejecutar la canalización en él. En su lugar, es posible que tengas que aplicar una lógica diferente para correlacionar la salida de la cola de mensajes fallidos con el elemento original, o bien interpretar y procesar el elemento parcialmente transformado. También puede provocar resultados incoherentes. Por ejemplo, si los elementos se envían por dos ramas de una canalización y cada rama envía elementos que provocan excepciones a una cola de mensajes fallidos, un solo elemento de entrada puede llegar a una, a otra, a ambas o a ninguna de las ramas.
Tiempo de espera de registros caros
Es posible que las canalizaciones dejen de responder mientras procesan un pequeño subconjunto de elementos que son más caros o que alcanzan una limitación que provoca que no respondan, como un bloqueo. Para mitigar este problema, algunas transformaciones te permiten definir un tiempo de espera y fallar los elementos con tiempo de espera agotado en cualquier DoFn de código de usuario que se encuentre con este problema. Por ejemplo, puedes usar el método with_exception_handling de Python. Cuando usas
tiempos de espera con una cola de mensajes fallidos, tu canalización puede seguir procesando elementos
correctos y avanzar, y puedes volver a procesar los elementos costosos
por separado. Esta configuración puede suponer un coste en términos de rendimiento.
Para determinar qué operaciones de DoFn es probable que requieran un tiempo de espera, realiza pequeños experimentos antes de lanzar tu canalización completa.
Habilitar el autoescalado vertical
Si no sabes cuánta memoria necesita tu trabajo o crees que corre el riesgo de quedarse sin memoria, habilita el escalado automático vertical. Esta función ayuda a evitar errores de falta de memoria cuando las canalizaciones se ejecutan a mayor escala o cuando se encuentran elementos excepcionalmente grandes.
Como el autoescalado vertical puede aumentar el coste de tu trabajo y no evita todos los errores por falta de memoria, debes solucionar los problemas de consumo excesivo de memoria. El autoescalado vertical también requiere Dataflow Prime, que tiene limitaciones adicionales y un modelo de facturación diferente.
Usar la ejecución especulativa para evitar retrasos
En el caso de las canalizaciones por lotes, puedes habilitar la ejecución especulativa, una función que te permite mitigar el impacto de las tareas que se ejecutan lentamente o que se bloquean. Estas tareas lentas o bloqueadas también se conocen como rezagadas. Esta función inicia ejecuciones redundantes o de copia de seguridad de las tareas que tardan demasiado. Se usa la primera tarea que se completa y se cancela la otra, lo que puede mejorar el tiempo de finalización general de tu canalización.
La ejecución especulativa puede ayudar a que las canalizaciones se completen más rápido proporcionando una ruta de ejecución alternativa para los elementos de trabajo que experimentan retrasos debido a máquinas de trabajo lentas u otros problemas transitorios, como errores no deterministas, limitación de recursos o problemas de conectividad.
Limitaciones y consideraciones
Antes de habilitar la ejecución especulativa, ten en cuenta lo siguiente:
- Pipelines de streaming: no se admite la ejecución especulativa en pipelines de streaming.
- Posible cambio en el coste: es difícil estimar el impacto de esta función en el coste, ya que es difícil predecir los rezagados y el aprovisionamiento de tareas de copia de seguridad. Por ejemplo, aunque un elemento de trabajo de copia de seguridad consume recursos adicionales, lo que puede aumentar los costes, su finalización anticipada puede llevar a un ahorro de recursos y a una reducción de los costes. En ambos casos, se espera que el impacto general sea mínimo.
- Elementos de trabajo de larga duración coherentes: la ejecución especulativa puede no ser de gran ayuda con los elementos de trabajo de larga duración coherentes, como las teclas de acceso rápido, ya que el problema subyacente que provoca la lentitud seguiría persistiendo.
Para obtener más información sobre las tareas que se retrasan en los trabajos por lotes, consulta Solucionar problemas de tareas que se retrasan en los trabajos por lotes.
Habilitar la ejecución especulativa
Para habilitar la ejecución especulativa, usa la opción de servicio map_task_backup_mode de Dataflow. Hay dos modos disponibles:
Java
--dataflowServiceOptions=map_task_backup_mode=ON--dataflowServiceOptions=map_task_backup_mode=CAUTIOUS
Python o Go
--dataflow_service_options=map_task_backup_mode=ON--dataflow_service_options=map_task_backup_mode=CAUTIOUS
En el modo ON, se programa una tarea de copia de seguridad si el tiempo de ejecución previsto de la tarea original es aproximadamente un 20% más largo que el de una tarea nueva.
En el modo CAUTIOUS, se programa una tarea de copia de seguridad si el tiempo de ejecución previsto de la tarea original es aproximadamente un 70% más largo que el de una tarea nueva.
Para confirmar que la ejecución especulativa está habilitada, consulta los mensajes de registro. Busca las entradas que muestren que se han iniciado tareas de copia de seguridad. Esto confirma que se ha activado la ejecución especulativa. Para ver estos registros, ve al panel Registros de trabajos de tu canal (Trabajos > elige tu trabajo > sección Registros > Registros de trabajos). El mensaje de registro aparece de la siguiente manera:
Backup issued in step STEP_NAME. ADDITIONAL_INFORMATION.
Soluciones alternativas para las canalizaciones propensas a errores
Algunas canalizaciones son especialmente propensas a errores. Aunque es mejor solucionar la causa de estos errores, para reducir el coste de los fallos, puede usar las siguientes opciones.
Materializar resultados intermedios
Las canalizaciones pueden tener una o varias transformaciones especialmente costosas que dominen el tiempo de ejecución de la canalización. Los errores de la canalización después de esta transformación pueden ser especialmente perjudiciales, ya que se pierde todo el trabajo que ya se ha completado. Para evitar esta situación, puedes escribir los PCollections intermedios generados por pasos costosos en un sumidero como Cloud Storage. Esta configuración reduce el coste de un fallo. Debes sopesar esta ventaja con el coste de realizar la escritura adicional. Puedes usar este resultado materializado de una de las siguientes formas:
- Divide la canalización original en dos: una que escriba el resultado intermedio y otra que lo lea.
- Solo si falla la canalización, lee y aplana los resultados de tu fuente original y de tu colección intermedia materializada.
Para asegurarte de que estas materializaciones se escriban antes de que se procesen más datos, añade un paso de espera (consulta el wait
class) antes de cualquier otro paso de procesamiento.