La inferencia de modelos de Machine Learning en entornos de producción a gran escala presenta desafíos significativos en cuanto a latencia, fiabilidad y la capacidad de iterar rápidamente. Un problema fundamental es cómo enrutar eficientemente las solicitudes de inferencia a la instancia de modelo correcta, en el shard de clúster adecuado, para el usuario y caso de uso específicos, sin exponer la complejidad subyacente a los servicios cliente o a los investigadores de ML.
La solución inicial de Netflix, Switchboard, abordó la abstracción y la flexibilidad para la experimentación, pero introdujo latencia y un punto único de fallo crítico. La evolución hacia Lightbulb y la integración con Envoy es una respuesta directa a estos problemas de escalabilidad, buscando optimizar la ruta de datos sin sacrificar la capacidad de gestión del plano de control.
Este patrón de evolución arquitectónica es común en sistemas distribuidos a medida que crecen: se comienza con una solución centralizada para la simplicidad y la funcionalidad rápida, y luego se descentraliza y optimiza la ruta de datos a medida que las restricciones de rendimiento y fiabilidad se vuelven primordiales. Refleja la tensión inherente entre la flexibilidad de un plano de control y la eficiencia de un plano de datos.
Arquitectura del Sistema
La arquitectura inicial se centró en Switchboard, un servicio de proxy centralizado que actuaba como punto de entrada único para todas las solicitudes de inferencia de modelos ML. Switchboard realizaba enrutamiento consciente del contexto, enriquecimiento de entradas y gestión del ciclo de vida de los modelos (shadow mode, canaries, rollbacks). Los clientes se integraban una única vez con Switchboard, que luego usaba 'Objectives' (enumeraciones que representan casos de negocio) y 'Switchboard Rules' (configuraciones JavaScript definidas por investigadores) para determinar el modelo y la versión adecuados, y enrutar la solicitud al VIP del clúster de serving correspondiente.
Las 'Switchboard Rules' se gestionaban a través de un sistema de pub-sub (Gutenberg de Netflix) para asegurar versionado, carga dinámica y rollbacks. El plano de control de Switchboard se encargaba de la asignación de modelos a shards, validación y mapeo de VIPs. El plano de datos realizaba la asignación de celdas A/B (consultando una plataforma de experimentación), selección de modelos y enrutamiento.
La evolución a Lightbulb refactoriza esta arquitectura para eliminar Switchboard de la ruta crítica de la solicitud. Ahora, las 'Switchboard Rules' se dividen en 'Model Serving Configuration' (qué modelo usar) y 'Routing Rules' (a qué VIP enrutar). Lightbulb es un servicio ligero que consume el contexto mínimo de la solicitud, resuelve la 'Model Serving Configuration' para determinar un routingKey y un ObjectiveConfig. El routingKey se añade a los encabezados de la solicitud, y el ObjectiveConfig (que contiene el ID del modelo y otros parámetros) se añade al cuerpo de la solicitud. El enrutamiento físico de la solicitud es realizado por Envoy, que ya se usa para todas las comunicaciones de egreso en Netflix. Envoy utiliza el routingKey del encabezado para mapear al VIP del clúster de serving apropiado, eliminando la necesidad de que Switchboard deserialice y re-serialice payloads grandes, y reduciendo la latencia al mover la lógica de enrutamiento al edge.
Flujo de Datos con Switchboard (Arquitectura Original)
- 1 Cliente Envía solicitud con UserId, Objective, Contexto
- 2 Switchboard Recibe solicitud, consulta Plataforma de Experimentación para asignación A/B
- 3 Switchboard Usa Switchboard Rules y asignación A/B para seleccionar modelo
- 4 Switchboard Enruta solicitud al VIP del clúster de Serving con el modelo seleccionado
- 5 Clúster de Serving Ejecuta workflow del modelo, devuelve respuesta
Flujo de Datos con Lightbulb + Envoy (Arquitectura Evolucionada)
- 1 Cliente Envía solicitud con UserId, Objective, Contexto
- 2 Lightbulb Recibe contexto mínimo, resuelve routingKey y ObjectiveConfig
- 3 Lightbulb Añade routingKey a encabezados, ObjectiveConfig a cuerpo de solicitud
- 4 Envoy Proxy Recibe solicitud, usa routingKey de encabezado para mapear a VIP
- 5 Envoy Proxy Enruta solicitud al VIP del clúster de Serving
- 6 Clúster de Serving Ejecuta workflow del modelo con ObjectiveConfig, devuelve respuesta
| Capa | Tecnología | Justificación |
|---|---|---|
| networking | Envoy | Proxy de borde para enrutamiento de tráfico de egreso, utilizado para el enrutamiento físico de solicitudes de inferencia basado en encabezados. |
| orchestration | Gutenberg (Netflix internal) | Sistema de pub-sub para la propagación de configuraciones dinámicas (Switchboard Rules), asegurando versionado, carga dinámica y rollbacks. |
| compute | Switchboard (Netflix internal) | Servicio de proxy centralizado inicial para enrutamiento consciente del contexto y gestión del ciclo de vida de modelos. vs AWS API Gateway, Service Mesh proxy (standalone) |
| compute | Lightbulb (Netflix internal) | Servicio ligero desacoplado que resuelve metadatos de enrutamiento (routingKey, ObjectiveConfig) para su consumo por Envoy y los clústeres de serving. |
| networking | gRPC | Protocolo de comunicación utilizado para los endpoints expuestos a los clientes. |
Trade-offs
Ganancias
- ▲ Reducción de latencia en la ruta crítica
- ▲ Eliminación de punto único de fallo
- ▲ Mejor aislamiento de tenants y tráfico
- ▲ Mayor flexibilidad para el cliente (visibilidad del origen de la solicitud)
Costes
- △ Mayor complejidad en la arquitectura de enrutamiento (más componentes)
/**
Configuration rule written by a Model Researcher to add an A/B experiment in the Model Serving system.
Cell 1: Uses the default, currently productized model
Cell 2 and Cell 3: Use different experimental (candidate) models
**/
function defineAB12345Rule() {
const abTestId = 12345;
const objectives = Objectives.ContinueWatchingRanking;
const abTestCellToModel = {
1: {name: "netflix-continue-watching-model-default"},
2: {name: "netflix-continue-watching-model-cell-2"},
3: {name: "netflix-continue-watching-model-cell-3"}
};
return {
cellToModel: abTestCellToModel,
abTestId: abTestId,
targetObjectives: [objectives],
modelInputType: constants.TITLE_INPUT_TYPE,
modelType: 'SCORER'
};
}Fundamentos Teóricos
El problema de enrutamiento en sistemas distribuidos a gran escala se relaciona con los principios de balanceo de carga y descubrimiento de servicios, que tienen raíces en la computación distribuida clásica. La idea de desacoplar el plano de control (gestión de reglas, asignación de modelos) del plano de datos (ejecución de enrutamiento) es un patrón arquitectónico bien establecido, a menudo visto en redes definidas por software (SDN) y en la evolución de los service meshes. La necesidad de enrutamiento consciente del contexto y la experimentación A/B se alinea con los principios de sistemas adaptativos y de auto-organización, donde el sistema ajusta su comportamiento (enrutamiento) basándose en condiciones externas (contexto del usuario, resultados de experimentos).
La gestión de configuraciones dinámicas y su propagación consistente a través de un sistema distribuido, como las 'Switchboard Rules' a través de Gutenberg, se basa en principios de sistemas de publicación/suscripción y eventualmente consistentes, similares a los discutidos en trabajos sobre bases de datos distribuidas y sistemas de coordinación como ZooKeeper o Paxos/Raft para la consistencia de metadatos. La optimización de la ruta de datos para reducir la latencia, especialmente al mover la lógica de enrutamiento al proxy de borde (Envoy), es una aplicación práctica de la ley de Amdahl y la búsqueda de minimizar los cuellos de botella en la ruta crítica.