Implementaciones de Actualización Continua con IPF SDK

Introducción

Las implementaciones de actualizaciones en línea son una estrategia crucial para mantener la disponibilidad del sistema durante las actualizaciones. Para evitar el tiempo de inactividad y garantizar la disponibilidad continua, un despliegue de actualización en línea actualiza un sistema de manera incremental — instancia por instancia o, en el caso de clústeres más grandes, varias instancias a la vez. Para garantizar que las actualizaciones continuas funcionen correctamente, todos los componentes de la nueva versión de su servicio de orquestación deben ser compatibles hacia atrás con la versión anterior.

El SDK de IPF utiliza muchas tecnologías, pero crucialmente la clave Marco de Orquestación de IPF se construye sobre Akka, un conjunto de herramientas potente para construir aplicaciones impulsadas por mensajes que son altamente concurrentes, distribuidas y resilientes, que proporciona un soporte robusto para actualizaciones continuas, particularmente al utilizar actores basados en eventos para la persistencia del estado, como lo hace IPF.

Este documento está dirigido a una audiencia técnica y describe el proceso y las consideraciones para implementar despliegues de actualización continua de servicios de orquestación construidos utilizando el SDK de IPF.

Lectura Requerida

Antes de avanzar más, asegúrese de tener al menos un conocimiento básico de lo siguiente:

Si bien no es necesario para comprender la estrategia, la familiaridad con lo siguiente puede ayudar a entender las razones detrás de algunas de las recomendaciones:

Estrategia de Despliegue de Actualización Continua

Un servicio de orquestación construido con el SDK de IPF representa una aplicación con estado que se despliega como un único Akka cluster. Como consecuencia, realizar actualizaciones continuas en un sistema de este tipo requiere una estrategia más compleja de lo que sería el caso con un típico. HTTP microservicio.

Los siguientes pasos describen el proceso para realizar actualizaciones continuas de los servicios de orquestación de IPF.

Paso 1: Prepare la Nueva Versión

Durante una actualización continua, un reequilibrio de Akka ocurrirán fragmentos. Combinado con Akka recordando entidades Al estar habilitado, esto causará con frecuencia que instancias de flujos iniciados en una versión antigua de un nodo de servicio se reinicien en un nodo de servicio que ejecuta la nueva versión. Además del reequilibrio de Akka shards, ciertos transportes de mensajes (como Kafka, Pulsar, AWS Kinesis, etc.) también necesitarán realizar la reasignación de particiones a medida que se detienen los nodos consumidores antiguos y se inician los nuevos.

Todo el trabajo de reequilibrio que se realiza como parte de una actualización continua puede causar que los flujos sensibles al tiempo se agoten, especialmente si la actualización continua se está llevando a cabo mientras el servicio está procesando volúmenes cercanos a su capacidad.

Para evitar un gran impacto en el procesamiento, se aconseja programar sus actualizaciones durante los períodos de bajo volumen típicos de su servicio.

Mantener la compatibilidad hacia atrás requiere lo siguiente:

  • Asegurando que las versiones de flujo existentes no cambien — una vez liberada, una versión de flujo debe considerarse inmutable.

    • Cambiar un flujo sin versionado introduce imprevisibilidad: un flujo en ejecución iniciado en la versión anterior del servicio puede no ser capaz de avanzar al ser rehidratado en la nueva versión del servicio debido a diversas incompatibilidades y, por lo tanto, podría quedar atrapado en un bucle infinito de recuperación-fallo.

    • Si un flujo necesita ser actualizado — cambios en las transiciones, introducción de nuevos estados, etc. — se debe crear una nueva versión del flujo y los cambios deben realizarse en esa versión. Ver Flujos de Versionado en la sección del tutorial para instrucciones sobre cómo hacer esto.

  • Asegurando que no se eliminen versiones de flujo activas de la nueva versión del servicio.

    • Eliminar una versión de flujo presente en la versión anterior del servicio abre la puerta a la orfandad de flujos en curso. IPF utiliza Akka Cluster roles para decidir qué nodos pueden alojar qué flujos. Si para el momento en que la actualización continua alcance el nodo final aún hay algunos flujos en curso que están ejecutando la versión eliminada, el clúster se encontrará en un estado en el que ningún nodo será capaz de alojar la versión antigua del flujo, lo que causará que el flujo en curso quede huérfano y atrapado para siempre en un estado incompleto.

    • Si la versión anterior de su servicio tenía la capacidad de iniciar un número de flujos de una cierta versión, esos flujos no deben ser eliminados en la nueva versión.

    • Elimine los flujos solo cuando no haya instancias en curso de los mismos y la versión anterior no tenga forma de iniciarlos.

    • Para determinar si se puede iniciar un cierto flujo, debe inspeccionar sus reglas de enrutamiento de flujo (cubiertas en el siguiente punto).

  • Proporcionando reglas de enrutamiento para los nuevos flujos y actualizando las reglas para los antiguos.

    • Selección de Versión de Flujo Basada en el Contexto le permite crear reglas de enrutamiento basadas en la configuración que dependen de los encabezados de los mensajes para realizar el enrutamiento a diferentes versiones de un flujo.

    • Alternativamente, como se indica en Flujos de Versionado, usted tiene control programático directo sobre qué versión de un flujo iniciar, por lo que crear reglas de enrutamiento arbitrarias también es una posibilidad.

    • Por defecto, si no se especifica una versión, se utiliza la más reciente.

    • Dependiendo del nivel de confianza en la corrección de sus nuevas versiones de flujo, puede decidir seguir iniciando las versiones antiguas hasta que se cumplan ciertas condiciones — un customer con una bandera de características inicia el flujo, el mensaje de inicio contiene un encabezado específico, se aplica un predicado de configuración estática, etc. La selección de versiones basada en el contexto mencionada anteriormente también puede ser utilizada para realizar pruebas canary y permitirle migrar lentamente a una nueva versión de un flujo. Ver Selección de Versión de Flujo Basada en Contexto para Pruebas Canary para más detalles.

  • Manteniendo la compatibilidad con los esquemas de eventos existentes.

    • Los esquemas están definidos por los elementos de datos empresariales enumerados para el evento en el DSL.

    • Romper un esquema de evento significará que sus flujos en vuelo no podrán ser recuperados en un rebalanceo, dejándolos huérfanos y sin poder completarse sin una implementación de hotfix.

    • Incluso si un flujo no cambia los elementos de datos comerciales de un evento, aún podría ocurrir un cambio no intencionado en un tipo utilizado en algún lugar del gráfico de objetos, por ejemplo, al actualizar una versión de una biblioteca común.

    • Para asegurar que los esquemas de eventos no se rompan, usted debe crear un conjunto de pruebas que verifique sus esquemas en el momento de la construcción.

    • Si por alguna razón poco probable no puede evitar romper un esquema de evento, puede utilizar el IPF domain event schema evolution support como último recurso.

  • Asegurando que los consumidores de respuesta de dominio externo sean compatibles hacia atrás.

    • Los consumidores que procesan respuestas de sus dominios externos deben ser capaces de enviar las entradas adecuadas tanto a las versiones antiguas como a las nuevas de sus flujos.

    • No apoyar las versiones antiguas además de las nuevas causará que los flujos de la versión antigua en curso se agoten o queden huérfanos en un estado inconsistente.

  • Evitando cambios disruptivos en lo expuesto APIs— si su servicio define una API que otros componentes integran con, la API debe seguir siendo compatible hacia atrás.

Paso 2: Actualizar Configuración

Actualice la configuración de implementación para soportar actualizaciones continuas:

  • Asegúrese Akka la configuración ha cambiado de maneras compatibles.

    • Bastantes Akka Las opciones de configuración — particularmente relacionadas con el agrupamiento, por ejemplo, las estrategias del Resolutor de Cerebros Divididos, el número de fragmentos, etc. — requieren que todos los nodos en el clúster estén configurados con el mismo valor para poder formar un clúster con éxito.

    • Si necesita cambiar un Akka valor de configuración que requiere consistencia en todo el clúster, deberá apagar todo su clúster.

  • Asegúrese de que la configuración de IPF haya cambiado de maneras compatibles.

    • La configuración relacionada con los reintentos de acción y los tiempos de espera es sensible a los cambios de versión del flujo, consulte Flujos de Versionado para más detalles.

    • Debe aplicar una consideración cuidadosa al actualizar ciertos journal processor configuraciones ya que pueden romper la compatibilidad de actualización continua:

      • Aumentar el número de particiones de eventos (consulte Particionamiento Events para más detalles) puede causar retrasos en el procesamiento, especialmente si el procesador de revistas se despliega como una aplicación separada. En esos escenarios, debe asegurarse de que la configuración del procesador de registros esté actualizada y desplegada antes de comenzar a desplegar su servicio de orquestación.

      • Usando EVENT_STREAM_PER_TAG como su event-streaming-type en combinación con la iniciación de nuevas versiones de flujo antes de que la actualización en curso esté completa causará errores de deserialización y, dependiendo de la configuración de manejo de errores de su procesador de diario, incluso puede resultar en la pérdida permanente de datos.

        Si está utilizando pruebas de canario de flujo a través de la selección de versiones, usted puede configurar la selección de versiones de tal manera que asegure que las nuevas versiones de flujo se inicien únicamente con su aprobación, mitigando así el riesgo de errores y pérdida de datos.

Paso 3: Despliegue de la Nueva Versión de Manera Incremental

Despliegue la nueva versión en un subconjunto de nodos, asegurando que el sistema permanezca operativo:

  • Comience actualizando un pequeño número de nodos (por ejemplo, el 10% del clúster).

  • Aumente gradualmente el porcentaje de nodos actualizados hasta que todo el clúster esté ejecutando la nueva versión.

  • Monitoree el servicio para detectar cualquier problema en el procesamiento.

  • Dependiendo de las reglas de enrutamiento, genere tráfico que inicie las nuevas versiones del flujo para asegurar que están funcionando correctamente.

    • Incluso si su pipeline de CD implica un entorno de pre-producción que refleja de cerca la producción, y ha realizado pruebas exhaustivas de sus nuevas versiones de flujo en pre-producción, puede ser recomendable aumentar lentamente la iniciación de nuevas versiones de flujo justo después del despliegue, especialmente si los flujos están llamando a nuevos endpoints de servicios externos.

    • Puede confiar en el métricas de la aplicación existente para rastrear qué versiones de qué flujos están siendo iniciadas y completadas.

Paso 4a: Complete la Actualización

Una vez que todos los nodos hayan sido actualizados y validados:

  • Siga monitoreando el sistema para cualquier problema posterior a la actualización.

    • En este momento, cualquier problema que se encuentre probablemente será resuelto por sus procedimientos habituales de corrección de errores.

  • Siéntase libre de eliminar cualquier código y configuraciones obsoletas relacionadas con la versión anterior.

    • Esto incluye versiones de flujo que ya no están activas en su servicio; con todas las instancias en curso de los flujos antiguos completadas en producción y las reglas de enrutamiento que impiden que se inicien nuevamente, ya no serán necesarias en la próxima versión de su servicio.

    • Por otro lado, si no le preocupa el tamaño de sus archivos JAR, no hay inconveniente en mantener los flujos antiguos, especialmente si desea permitirse la capacidad de construir procesadores de diarios que funcionen con todos los datos históricos en el diario.

  • Documente el proceso de actualización y las lecciones aprendidas para referencia futura.

Paso 4b: Revertir

En el improbable escenario de que se descubra un problema con una de las nuevas versiones del flujo solo cuando usted ha desplegado en producción, puede considerar revertir a la versión anterior.

Aquí hay algunas cosas que debe considerar antes de revertir:

  • Todas las instancias en vuelo de las nuevas versiones del flujo quedarán huérfanas y atascadas una vez que realice la reversión.

    • Incluso con Akka Recuerde que, con las entidades habilitadas, no hay nada que se pueda hacer para permitir la reactivación de esos flujos en la versión antigua del servicio de orquestación, ya que el código necesario para ejecutarlos ya no existe.

  • Si las versiones antiguas de sus flujos están funcionando correctamente — es decir, el error está presente solo en las nuevas versiones de los flujos — entonces simplemente revertir sus reglas de enrutamiento para evitar la iniciación de los nuevos flujos podría ser suficiente.

    • Dependiendo de cómo configure sus reglas de enrutamiento, esto puede o no requerir un reinicio de todos los nodos en el clúster.

    • Revertir las reglas de enrutamiento no dejará huérfanas ninguna de las flujos, pero el problema subyacente puede seguir dejando los flujos atascados y puede ser necesaria alguna intervención manual.

    • A diferencia de realizar un retroceso completo de la versión del servicio, revertir las reglas de enrutamiento le permitiría crear utilidades ad-hoc que programáticamente abortar cualquiera de los flujos que están atascados, o al menos pasivar ellos. Usando el Transaction Operations API también es una opción para crear scripts de recuperación ad-hoc.

Tiempo de inactividad requerido

Si bien el despliegue de actualización en línea ofrece varias ventajas, como una interrupción mínima y disponibilidad continua, hay escenarios en los que no se puede utilizar de manera efectiva y es necesario un tiempo de inactividad.

A continuación se presentan algunas circunstancias que pueden impedir el uso de actualizaciones en línea.

Cambios de base de datos incompatibles

Cuando una nueva versión de una aplicación requiere cambios en la base de datos que no son compatibles hacia atrás, las actualizaciones en línea pueden ser problemáticas o incluso inalcanzables.

Mientras que el SDK de IPF promete mantener los esquemas de base de datos compatibles hacia atrás, algunos cambios pueden estar fuera del control del SDK de IPF (por ejemplo,Akka cambiando sus representaciones internas) y algunos cambios pueden resultar necesarios para cumplir con objetivos no funcionales (por ejemplo, particionar o estructurar colecciones de manera diferente para hacer ciertas consultas más eficientes).

Actualizaciones de Dependencias

Si la nueva versión del servicio depende de una actualización a una dependencia crítica que no es compatible hacia atrás, las actualizaciones en línea pueden no ser viables.

Ejemplos incluyen:

  • Actualización a una nueva versión de una base de datos o cola de mensajes que requiere una actualización simultánea de todos los servicios de cliente.

  • Actualización a una nueva versión del SDK de IPF. En este momento, el SDK de IPF no admite implementaciones heterogéneas; todas las instancias deben utilizar la misma versión del SDK.

  • Introduciendo una nueva versión de un marco o biblioteca con la que la versión anterior de la aplicación no puede integrarse — p. ej. Akka actualización de versión que rompe la compatibilidad binaria con la versión anterior del servicio, impidiendo efectivamente que las instancias de la nueva versión formen un clúster con la anterior.

Vulnerabilidades de Seguridad

Si la nueva versión aborda vulnerabilidades de seguridad críticas que deben ser parcheadas de inmediato, una actualización continua puede no ser lo suficientemente rápida para mitigar el riesgo. En tales casos, puede ser necesario un despliegue completo para garantizar que todas las instancias se actualicen simultáneamente, ya que las actualizaciones retrasadas pueden exponer el sistema a amenazas de seguridad.

Conclusión

Las implementaciones de actualización continua con el SDK de IPF proporcionan una estrategia robusta y eficiente para mantener la disponibilidad del sistema durante las actualizaciones. Al aprovechar el Akka Las capacidades del toolkit para gestionar aplicaciones concurrentes, distribuidas y resilientes, el Marco de Orquestación de IPF asegura transiciones suaves entre versiones de servicio.

Consideraciones clave para actualizaciones continuas exitosas incluyen:

  • Compatibilidad hacia atrás: Asegúrese de que todos los componentes en la nueva versión del servicio sean compatibles hacia atrás para evitar interrupciones en la ejecución del flujo.

  • Actualizaciones de Configuración: Actualizar Akka y configuraciones de IPF cuidadosamente para mantener la compatibilidad en todo el clúster.

  • Despliegue Incremental: Despliegue la nueva versión de manera incremental para monitorear y abordar cualquier problema que surja sin afectar la disponibilidad general del servicio.

  • Monitoreo y Validación: Utilice las herramientas de monitoreo proporcionadas y el rastreo distribuido para validar el nuevo despliegue y solucionar cualquier problema.

  • Manejo de Actualizaciones y Reversiones: Prepárese tanto para la finalización de actualizaciones como para posibles reversiones comprendiendo las implicaciones para los flujos en curso y manteniendo flexibilidad en las reglas de enrutamiento.

Al seguir estas directrices, usted puede gestionar eficazmente las actualizaciones continuas, asegurando una mínima interrupción y manteniendo la disponibilidad continua del servicio. Documentar el proceso y las lecciones aprendidas ayudará a refinar futuras implementaciones, contribuyendo a la resiliencia y robustez de sus servicios de orquestación construidos con el SDK de IPF.