Prácticas recomendadas para canalizaciones de lotes grandes

En este documento, se explica cómo minimizar el impacto de las fallas de trabajo en canalizaciones de lotes grandes. Las fallas de cargas de trabajo grandes tienen un impacto particular debido al tiempo y el dinero necesarios para recuperarse de ellas y solucionarlas. Reintentar estas canalización desde cero cuando fallan es costoso en términos de tiempo y dinero.

Para reducir las fallas costosas de las canalizaciones por lotes, sigue los lineamientos que se indican en esta página. Debido a que no siempre puedes evitar por completo los elementos fallidos y las fallas de canalización, las técnicas proporcionadas se enfocan en aumentar la resiliencia, reducir el costo de las fallas y facilitar la depuración y la comprensión de las fallas cuando ocurren.

Para conocer las prácticas recomendadas generales de las canalizaciones, consulta Prácticas recomendadas para canalizaciones de Dataflow.

Ejecuta experimentos pequeños para trabajos grandes

Antes de ejecutar un trabajo por lotes grande, ejecuta uno o más trabajos más pequeños en un subconjunto del conjunto de datos. Esta técnica puede proporcionar una estimación de costos y ayudar a encontrar posibles puntos de fallo.

Costo estimado

Ejecutar experimentos puede proporcionar un valor mínimo estimado del costo total de ejecutar la tarea. Por lo general, el cálculo del costo del trabajo es cost of test job*size(full dataset)/size(test dataset). Según la canalización, el costo puede escalar de forma superlineal o, con menos frecuencia, sublinear. Sin embargo, este paso suele proporcionar una buena estimación aproximada del costo del trabajo. También puedes probar diferentes tamaños de entradas para obtener una mejor estimación de cómo se escalan tus costos. Usa esta información para decidir si deseas continuar con la canalización existente o reestructurarla para reducir los costos.

Cómo encontrar los puntos de fallo

Ejecutar experimentos puede exponer errores, posibles puntos de falla o posibles problemas de configuración y eficiencia. También puedes examinar otras métricas de la canalización, como las siguientes:

  • Si tu canalización usa casi toda la memoria disponible, es posible que experimente excepciones de memoria insuficiente (OOM) con una carga más alta o con registros excepcionalmente grandes. Es posible que debas aprovisionar más memoria para tu trabajo final para evitar estos errores de OOM.
  • Si tu canalización experimenta descensos en la capacidad de procesamiento, examina los registros de la canalización para determinar por qué. Es posible que encuentres un elemento bloqueado o una parte de tu conjunto de datos con un rendimiento particularmente bajo. Puedes procesar estos datos por separado o puedes aplicar un tiempo de espera cuando se procesan los elementos. Para obtener más información, consulta la sección Cómo establecer un tiempo de espera para los registros costosos en este documento.
  • Si tu canalización tiene un rendimiento mucho peor en una tarea en Dataflow que de forma local, examina la lógica de la canalización para descubrir el motivo. Por ejemplo, si obtienes la misma capacidad de procesamiento con ocho núcleos en Dataflow que con un núcleo de forma local, es posible que el trabajo tenga un cuello de botella en la contención de un recurso. Si consideras que tu rendimiento es peor de lo esperado, considera una o más de las siguientes opciones:
    • Ejecuta más experimentos con diferentes configuraciones de máquinas o software.
    • Realiza pruebas de forma local con varios núcleos al mismo tiempo.
    • Inspecciona tu código para encontrar posibles cuellos de botella cuando realices la implementación a gran escala.

Si tu canalización tiene alguna recomendación de Dataflow, síguela para mejorar el rendimiento.

Usa colas de mensajes no entregados para controlar datos incorrectos inesperados

Las canalización suelen tener éxito en la mayoría de los elementos de entrada, pero fallan en un subconjunto pequeño de la entrada. Es posible que no detectes este problema cuando ejecutes experimentos pequeños, ya que estos solo prueban un subconjunto de la entrada. De forma predeterminada, Dataflow vuelve a intentar estas tareas con errores cuatro veces en el modo por lotes y una cantidad ilimitada de veces en el modo de transmisión. En el modo por lotes, después de alcanzar el límite de reintentos, todo el trabajo falla. En el modo de transmisión, puede detenerse de forma indefinida.

En muchos trabajos, puedes excluir estos elementos con errores de la canalización y completar el resto del trabajo con una cola de mensajes no entregados. La fila de buzón de destino pasa los registros con errores a un PCollection de salida independiente, que puedes administrar por separado de tu salida principal. Esta configuración te permite diseñar una política para estos registros. Por ejemplo, puedes escribirlos en Pub/Sub de forma manual, inspeccionarlos y limpiarlos, y, luego, volver a procesar los registros.

Muchas transformaciones de Apache Beam incluyen compatibilidad integrada con las filas de buzón de destino. En Java, puedes acceder a ellos con un objeto ErrorHandler. En Python, puedes acceder a ellos con el método with_exception_handling. Algunas transformaciones tienen formas personalizadas de definir colas de buzón de destino, sobre las que puedes obtener información en la documentación de la transformación. Para obtener más información, consulta Usa colas de mensajes no entregados para el manejo de errores.

Para determinar si tu trabajo cumple con los criterios de una cola de buzón de destino, consulta la sección Limitaciones de este documento.

Limitaciones de la cola de mensajes no entregados

En las siguientes situaciones, es posible que una cola de mensajes no entregados no sea útil:

  • Fallas de ciclo de vida de DoFn o del trabajador completo Si el procesamiento falla en todo el trabajador o paquete, una cola de buzón de destino no puede detectar la falla. Por ejemplo, si tu canalización encuentra una excepción de memoria insuficiente (OOM), todas las tareas activas en la VM fallan y se vuelven a intentar, sin enviar nada a la cola de buzón devuelto.
  • Combinaciones o alguna otra agregación 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 cuando uses una fila de bandeja de elementos no entregados antes de este paso. El uso de una fila de bandeja de elementos eliminados excluye parte de tus datos de entrada del resultado. Agregar una cola de mensajes no entregados podría cambiar la exactitud por la tolerancia a errores.
  • Errores en la ruta de acceso de la cola de mensajes no entregados Si un elemento falla mientras se envía al receptor de la cola de mensajes no entregados, toda la canalización puede fallar. Para evitar esta falla, mantén la lógica de la cola de mensajes no entregados lo más básica posible. Puedes agregar un paso de espera (consulta wait class) para asegurarte de que la entrada principal termine antes de escribir los elementos de la cola de buzón devuelto. Esta configuración podría reducir el rendimiento y retrasar los indicadores de error de tu canalización.
  • Elementos transformados parcialmente. Si insertas una cola de mensajes no entregados en algún punto de la canalización, es posible que esta emita el elemento transformado parcialmente y no tenga acceso al elemento original. Como resultado, no puedes limpiar el elemento ni volver a ejecutar la canalización en él. En su lugar, es posible que debas aplicar una lógica diferente para correlacionar el resultado de la cola de mensajes no entregados con el elemento original, o bien que debas interpretar y procesar el elemento transformado parcialmente. También podría generar resultados incoherentes. Por ejemplo, si los elementos se envían a dos ramas de una canalización y cada rama envía elementos que generan excepciones a una cola de buzón devuelto, un solo elemento de entrada puede llegar a una, a la otra, a ambas o a ninguna de las ramas.

Cómo establecer un tiempo de espera para los registros costosos

Es posible que los canales dejen de responder mientras procesan un subconjunto pequeño de elementos que son más costosos o que alcanzan una limitación que causa que no respondan, como un interbloqueo. Para mitigar este problema, algunas transformaciones te permiten establecer un tiempo de espera y marcar como fallidos los elementos que se agoten en cualquier DoFn de código de usuario que encuentre este problema. Por ejemplo, puedes usar el método with_exception_handling de Python. Cuando usas tiempos de espera con una cola de mensajes no entregados, tu canalización puede seguir procesando elementos sin errores y avanzar, y puedes volver a procesar los elementos costosos por separado. Esta configuración puede generar un costo de rendimiento.

Para determinar qué operaciones de DoFn es probable que requieran un tiempo de espera, ejecuta experimentos pequeños antes de iniciar tu canalización completa.

Habilitar el ajuste de escala automático vertical

Si no sabes cuánta memoria necesita tu trabajo o crees que corre el riesgo de quedarse sin memoria, habilita el ajuste de escala automático vertical. Esta función ayuda a evitar fallas de OOM cuando las canalizaciones se ejecutan a mayor escala o cuando encuentran elementos excepcionalmente grandes.

Debido a que el ajuste de escala automático vertical puede aumentar el costo de tu trabajo y no evita todas las fallas de falta de memoria, de cualquier manera, debes abordar los problemas de consumo excesivo de memoria. El ajuste de escala automático vertical también requiere Dataflow Prime, que tiene limitaciones adicionales y un modelo de facturación diferente.

Soluciones alternativas para canalizaciones propensas a fallas

Algunas canalizaciones son particularmente propensas a errores. Si bien es mejor abordar la fuente de estos errores, para reducir el costo de las fallas, considera las siguientes opciones.

Materializa los resultados intermedios

Las canalizaciones pueden tener una o más transformaciones particularmente costosas que dominan el tiempo de ejecución de la canalización. Los errores de canalización después de esta transformación pueden ser particularmente dañinos, ya que se pierde todo el trabajo que ya se completó. Para evitar esta situación, considera escribir PCollections intermedios generados por pasos costosos en un receptor como Cloud Storage. Esta configuración reduce el costo de una falla. Debes sopesar esta ventaja con el costo de realizar la escritura adicional. Puedes usar este resultado materializado de una de las siguientes maneras:

  1. Divide tu canalización original en dos: una que escriba el resultado intermedio y otra que lo lea.
  2. Solo en caso de falla de la canalización, lee y aplana los resultados de la fuente original y de la colección intermedia materializada.

Para asegurarte de que estas materializaciones se escriban antes de continuar con el procesamiento, agrega un paso de espera (consulta wait class) antes de los pasos de procesamiento posteriores.