A medida que los microservicios basados en eventos se convierten en una de las arquitecturas más populares para crear sistemas distribuidos, coherentes con los datos y a gran escala, muchas empresas se enfrentan a la ecuación definitiva de eficiencia del sistema frente a coste. Estar preparado para la afluencia de datos a gran escala en cualquier momento manteniendo el coste de computación al mínimo es un reto al que también nos hemos enfrentado en Trax. En este blog mostraremos nuestra solución específica utilizando algunas de las API básicas que ofrecen todos los proveedores de nube. Este enfoque innovador nos ha ayudado a minimizar los retrasos en el sistema y ahorrar ~65% del coste de computación.
Esta innovación de vanguardia fue presentada por AWS en un episodio de This is My Architecture.
En Trax digitalizamos el mundo físico del comercio minorista mediante visión por ordenador. La transformación de imágenes individuales de estanterías en datos y perspectivas sobre las condiciones de las tiendas es posible gracias a la "Fábrica Trax". Construida con una arquitectura asíncrona basada en eventos, la Fábrica Trax es un clúster de microservicios en el que la finalización de un servicio desencadena la activación de otro.
Arquitectura de la fábrica de visión por ordenador Trax
En este blog se analiza la necesidad de una infraestructura robusta y escalable para dar soporte a la Fábrica Trax y se presentan soluciones innovadoras desarrolladas por los ingenieros de Trax para añadir y eliminar capacidad en función de la demanda. Aprenda cómo Trax construyó un sistema de procesamiento de mensajes basado en grupos de autoescalado EC2 para SNS/SQS que puede escalar cada segundo. Nuestra solución va más allá del clásico escaneo de profundidad de colas de 5 minutos con CloudWatch, lo que nos permite reducir el tiempo de inactividad, evitar pérdidas de datos y mejorar los niveles generales de servicio.
La necesidad de escala
A principios de los 90, Electronic Arts publicó un videojuego de carreras llamado Need for Speed en el que los jugadores debían completar varios tipos de carreras mientras evadían a las fuerzas del orden en persecuciones policiales.
También fue en la misma época en la que los ordenadores utilizados por varias empresas estaban cada vez más difundidos, y los científicos y tecnólogos exploraron formas de poner la potencia de cálculo a gran escala a disposición de más usuarios a través del tiempo compartido. Así comenzó la era de la computación en nube y, con ella, el reto permanente de la optimización de infraestructuras. En este juego de Necesidad de Escala, los equipos de infraestructura añaden y eliminan capacidad del sistema mientras se adhieren a las leyes establecidas por los directores de operaciones, directores financieros y directores técnicos. Los ingenieros de Trax, al igual que sus homólogos de otras empresas tecnológicas basadas en la nube, necesitaban optimizar la escala al tiempo que mejoraban los niveles de servicio al cliente, reducían costes y conservaban la simplicidad del sistema informático.
El reto de la ampliación en Trax
Trax cuenta con la plataforma de visión por ordenador para minoristas más avanzada del sector, con un sofisticado sistema backend que procesa millones de imágenes de estanterías cada mes.
Una nueva imagen que entra en el sistema es uno de los principales eventos gestionados por el backend Trax. Este evento activa un microservicio que reconoce los productos en la imagen utilizando algoritmos avanzados de aprendizaje profundo. Este proceso es asíncrono en el sentido de que no hay ningún otro microservicio que esté esperando una respuesta de este servicio de reconocimiento de imágenes. Su tarea finaliza cuando publica un evento una vez que completa la actividad de procesamiento y proporciona los resultados. Varios microservicios de la Fábrica Trax funcionan de esta manera, realizando constantemente numerosas actividades, como cosido, geometría y muchas más, cada una de ellas con diferentes grados de complejidad computacional.
Transformar millones de imágenes de múltiples proyectos en todo el mundo en información específica para los clientes requiere mucha potencia de cálculo y supone una carga para los presupuestos de TI.
Normalmente, las decisiones sobre si reducir o aumentar la capacidad (añadir o reducir máquinas, respectivamente) se toman en función de las métricas básicas de profundidad de la cola proporcionadas por los proveedores de la nube, por ejemplo, cuántos mensajes hay en la cola.
Hay dos obstáculos importantes para esta política de ampliación:
- El tiempo de calentamiento de una máquina nueva es de ~3 minutos
- Los proveedores de la nube informan del número de mensajes en la cola una vez cada 5 minutos
En un sistema complejo como Trax, en el que las imágenes entran en la fábrica en volúmenes variables y la carga de cada servicio es diferente de la de los demás, la información sobre la profundidad de las colas se vuelve obsoleta en intervalos de 5 minutos. Esto presenta el riesgo no sólo de detectar muy tarde la potencia de cálculo necesaria y perjudicar los acuerdos de nivel de servicio, sino también de incurrir en costes adicionales al realizar ajustes de escala.
Ilustración de Scaling Monitor utilizando métricas de capacidad listas para usar
- El gráfico amarillo indica el número previsto de máquinas necesarias teniendo en cuenta el total de mensajes en cola y mensajes en proceso
- El gráfico verde es el número real de máquinas en la plataforma en nube
Como indica el gráfico, confiar en las métricas preestablecidas para supervisar la utilización de la capacidad cada 5 minutos da lugar a incurrir en costes en máquinas que no están en uso, así como a perjudicar los niveles de servicio al hacer funcionar máquinas inadecuadas (por ejemplo, entre las 10.00 y las 12.00 en el gráfico).
Más allá de la profundidad de las colas como medida de escala
La profundidad de la cola ha sido y seguirá siendo un factor de influencia clave en las decisiones de escalado dentro de los sistemas basados en eventos. Pero basarse únicamente en la profundidad de la cola como métrica de escalado crea un enfoque reactivo de la optimización de la infraestructura.
Cuando hay un mensaje esperando en una cola, ocupa un valioso tiempo de cálculo que preferiríamos dedicar a un mensaje que está siendo procesado por un servicio. Por eso, lo ideal es disponer de cierta cantidad de potencia de cálculo de reserva en un momento dado. Estos sistemas de reserva esperan a que lleguen nuevos mensajes a la cola para poder procesarlos inmediatamente sin retrasos. Naturalmente, este enfoque proactivo es mejor que tener que añadir máquinas cuando los mensajes ya están en la cola y escalarlas cuando la cola ya está vacía. La necesidad de potencia de reserva revela una idea importante: la profundidad de la cola no lo dice todo.
Por tanto, la ecuación correcta para el escalado debería ser, de hecho:
Demanda = Mensajes en cola + mensajes en proceso + máquinas libres
Razones para medir con más frecuencia la capacidad y la carga
Como hemos establecido en las secciones anteriores, depender de las métricas de escalado sólo una vez cada 5 minutos no sólo es costoso, sino que también dificulta los niveles de servicio y la satisfacción del cliente. Para superarlo, desarrollamos un servicio que mide la profundidad de la cola y los mensajes en proceso cada segundo a través de la API. Comparando el antiguo método de muestreo con el nuevo, las mejoras fueron muy claras. En la siguiente ilustración, la demanda (línea amarilla) nunca supera la oferta (línea verde).
Obsérvese que cuando la demanda aumenta bruscamente, la oferta reacciona muy rápido protegiendo eficazmente a nuestros clientes de desagradables retrasos en el servicio.
Además, este método ayuda a mantener nuestra potencia informática sobrante en estrecha alineación con la demanda, en lugar de gastarla en instancias ociosas que están esperando nuevos mensajes.
Escalar con cuidado
El escalado agresivo realizado de forma incorrecta tiene un peligro claro y presente: la posibilidad de escalar en máquinas que aún están procesando información. En la fábrica Trax, por ejemplo, los algoritmos basados en la geometría suelen ocupar más tiempo de procesamiento que otros servicios. Quitar potencia de cálculo a este servicio demasiado pronto tiene como consecuencia que el mensaje se devuelva a la cola. En consecuencia, además de indicar la afluencia natural al sistema, los informes de demanda incluyen mensajes que vuelven a la cola por segunda vez, y puede que vuelvan por tercera o cuarta vez. Esta carga puede aumentar drásticamente con el tiempo y repercutir tanto en los costes como en los niveles de servicio.
Para evitar que esto ocurra, hemos implementado un mecanismo por el que se "bloquean" los servicios que levantan una bandera indicando que aún están procesando mensajes. Esto evita que tales instancias se vean sometidas a decisiones de escalado. La mayoría de los proveedores de nube ofrecen funciones que "protegen" instancias de forma selectiva. Una vez que el servicio termina de procesar los mensajes, retira la bandera y vuelve al conjunto de recursos informáticos que participan en el juego de escalado. Esta capacidad garantiza que sólo se escalen las máquinas inactivas.
En el gráfico anterior, vemos que la demanda y la oferta están en armonía. Pero fíjate en algo que antes no veíamos. Hay una nueva línea roja que siempre se mantiene cerca del eje X. Esta línea representa el retraso de nuestro sistema. En efecto, es el tiempo que el mensaje más antiguo permanece en la cola antes de ser procesado. El hecho de que las líneas oferta-demanda funcionen como deben, combinado con que el retardo sea cercano a cero en la mayoría de los momentos, significa que los niveles de servicio están indemnes.
Repliegue robusto
Como dice Werner Vogels, CTO de Amazon, "todo falla todo el tiempo". Hemos introducido un cambio tecnológico importante y hemos desarrollado un servicio que mide la profundidad de las colas y los mensajes en proceso y realiza una operación de escalado en nuestro sistema. Si este servicio falla, perderemos toda capacidad de escalado, que es de lo que están hechas las pesadillas de los directores de tecnología. Para evitarlo, se pone en marcha un plan de recuperación ante desastres. El mecanismo original de consulta de la profundidad de las colas cada 5 minutos sigue vigente y los dos sistemas funcionan en paralelo. De este modo, si uno de ellos falla, los niveles de servicio no se ven muy afectados.
Conclusiones
He aquí una representación de nuestra solución plenamente funcional trabajando en un día normal a mitad de semana:
Esto muestra una correlación perfecta entre las máquinas previstas (línea naranja) y las reales (línea azul), con suficiente potencia de cálculo de reserva. El tiempo durante el cual el mensaje más antiguo permanece en la cola antes de ser procesado (línea roja) es sistemáticamente bajo, con picos sólo durante periodos muy breves.
En resumen, la construcción de un mecanismo de escalado para sistemas asíncronos basados en eventos que Trax tiene cuatro pilares fundamentales:
- Identificar la métrica de demanda correcta: Utilizar la métrica correcta tanto de supervisión de la carga como de ejecución de decisiones de escalado.
- Muestreo frecuente: Medir y tomar medidas con mucha frecuencia
- Bloqueo a escala: Elimine los sistemas ocupados del juego del escalado
- Recuperación robusta: Evite tener un único punto de fallo y cuente siempre con un plan de recuperación ante desastres.
El éxito se define en función de lo contentos que estén con la solución los responsables del juego Need for Scale: el Director Financiero, el Director de Operaciones y el Director Técnico. El resultado de esta innovación beneficia a todos:
- (Coste) Ahorro de ~10.000 dólares mensuales en costes informáticos, utilizando exactamente el número de servidores que necesitamos.
- (SLA) Mejora del SLA, reduciendo el tiempo de espera en las colas
- (Simplicidad) Unificación de las colas de alta y baja prioridad en una sola cola
Michael Feinstein también impartió una sesión sobre este tema en Reversim 2018. Haga clic en el botón de reproducción para ver la sesión completa.