Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Ya existe una amplia gama de tecnologías para crear sistemas de procesamiento de flujos. Estos incluyen sistemas para almacenar de forma duradera datos de flujo (por ejemplo, Event Hubs y Kafka) y sistemas para expresar operaciones de proceso a través de datos de flujo (por ejemplo, Azure Stream Analytics, Apache Storm y Apache Spark Streaming). Estos son excelentes sistemas que permiten crear canalizaciones de procesamiento de flujos de datos eficaces.
Limitaciones de los sistemas existentes
Sin embargo, estos sistemas no son adecuados para el cálculo de forma libre de grano fino sobre datos en flujo. Los sistemas de proceso de streaming mencionados anteriormente le permiten especificar un gráfico unificado de flujo de datos de las operaciones aplicadas de la misma manera a todos los elementos de flujo. Se trata de un modelo eficaz cuando los datos son uniformes y desea expresar el mismo conjunto de operaciones de transformación, filtrado o agregación sobre estos datos. Sin embargo, otros casos de uso requieren expresar operaciones fundamentalmente diferentes en distintos elementos de datos. En algunos de estos casos, como parte del procesamiento, es posible que ocasionalmente necesite realizar una llamada externa, como invocar una API REST arbitraria. Los motores de procesamiento de flujos de flujo de datos unificados no admiten estos escenarios, los admiten de forma limitada y restringida, o no son eficaces para admitirlos. Esto se debe a que están intrínsecamente optimizados para un gran volumen de elementos similares y normalmente se limitan en términos de expresividad y procesamiento. Orleans Las secuencias tienen como destino estos otros escenarios.
Motivación
Todo comenzó con las solicitudes de Orleans los usuarios para admitir la devolución de una secuencia de elementos desde una llamada a un método de grain. Como se puede imaginar, eso era sólo la punta del iceberg; necesitaban mucho más.
Un escenario típico de Orleans Streams es cuando tiene flujos por usuario y quiere realizar un procesamiento diferente para cada usuario dentro del contexto de ese usuario individual. Es posible que tenga millones de usuarios, pero algunos están interesados en el tiempo y se suscriben a alertas meteorológicas para una ubicación determinada, mientras que otros están interesados en eventos deportivos; otra persona podría estar realizando un seguimiento del estado de un vuelo determinado. El procesamiento de estos eventos requiere una lógica diferente, pero no quiere ejecutar dos instancias independientes del procesamiento de flujos. Es posible que algunos usuarios solo estén interesados en un stock determinado y solo si se aplica una determinada condición externa, una condición que podría no formar parte necesariamente de los datos de la secuencia (y, por tanto, necesita comprobar dinámicamente en tiempo de ejecución como parte del procesamiento).
Los usuarios cambian sus intereses todo el tiempo, por lo que sus suscripciones a secuencias de eventos específicas vienen y van dinámicamente. Por lo tanto, la topología de streaming cambia de forma dinámica y rápida. Además, la lógica de procesamiento por usuario evoluciona y cambia dinámicamente en función del estado del usuario y de los eventos externos. Los eventos externos pueden modificar la lógica de procesamiento de un usuario determinado. Por ejemplo, en un sistema de detección de trampas en juegos, cuando se descubre un nuevo método de trampa, la lógica de procesamiento necesita actualizarse con la nueva regla para detectar esta infracción. Esto debe hacerse, por supuesto, sin interrumpir la canalización de procesamiento en curso. Los motores de procesamiento de flujos de flujo de datos masivos no se crearon para admitir estos escenarios.
Es casi sin decir que este sistema debe ejecutarse en varias máquinas conectadas a la red, no solo en un solo nodo. Por lo tanto, la lógica de procesamiento debe distribuirse de forma escalar y elástica en un clúster de servidores.
Nuevos requisitos
Se han identificado cuatro requisitos básicos para un sistema de procesamiento de flujos para dirigirse a los escenarios anteriores:
- Lógica de procesamiento de flujos flexible
- Compatibilidad con topologías altamente dinámicas
- Granularidad de flujo detallada
- Distribución
Lógica de procesamiento de flujos flexible
El sistema debe admitir diferentes formas de expresar la lógica de procesamiento de flujos. Los sistemas existentes mencionados anteriormente requieren que los desarrolladores escriban un gráfico de cálculo declarativo de flujo de datos, normalmente siguiendo un estilo de programación funcional. Esto limita la expresividad y flexibilidad de la lógica de procesamiento. Orleans los flujos son indiferentes a cómo se expresa la lógica de procesamiento. Se puede expresar como un flujo de datos (por ejemplo, mediante extensiones reactivas (Rx) en .NET), un programa funcional, una consulta declarativa o una lógica imperativa general. La lógica puede ser con estado o sin estado, puede que tenga o no efectos secundarios y puede desencadenar acciones externas. Toda la potencia va al desarrollador.
Compatibilidad con topologías dinámicas
El sistema debe permitir topologías en evolución dinámica. Los sistemas existentes mencionados anteriormente suelen limitarse a topologías estáticas fijas en el momento de la implementación que no pueden evolucionar en tiempo de ejecución. En el ejemplo siguiente de una expresión de flujo de datos, todo es agradable y sencillo hasta que necesite cambiarlo:
Stream.GroupBy(x=> x.key).Extract(x=>x.field).Select(x=>x+2).AverageWindow(x, 5sec).Where(x=>x > 0.8) *
Cambie la condición de umbral en el Where filtro, agregue una Select instrucción o agregue otra rama en el gráfico de flujo de datos y genere un nuevo flujo de salida. En los sistemas existentes, esto no es posible sin anular toda la topología y reiniciar el flujo de datos desde cero. Prácticamente, estos sistemas comprueban el cálculo existente y pueden reiniciarse desde el punto de control más reciente. Aun así, este reinicio es perjudicial y costoso para un servicio en línea que produce resultados en tiempo real. Este reinicio se vuelve especialmente poco práctico cuando se trabaja con un gran número de expresiones de este tipo ejecutadas con parámetros similares pero diferentes (por usuario, por dispositivo, etc.) que cambian continuamente.
El sistema debe permitir la evolución del gráfico de procesamiento de flujos en tiempo de ejecución agregando nuevos vínculos o nodos al gráfico de cálculo o cambiando la lógica de procesamiento dentro de los nodos de cálculo.
Granularidad de flujo detallada
En los sistemas existentes, la unidad más pequeña de abstracción suele ser todo el flujo (topología). Sin embargo, muchos escenarios de destino requieren un nodo o vínculo individual en la topología para que sea una entidad lógica. De este modo, cada entidad puede administrarse de forma independiente. Por ejemplo, en una topología de flujo grande que comprende varios vínculos, los distintos vínculos pueden tener características diferentes y implementarse en diferentes transportes físicos. Algunos vínculos pueden pasar por sockets TCP, mientras que otros usan colas fiables. Los diferentes enlaces pueden tener garantías de entrega diferentes. Los distintos nodos pueden tener diferentes estrategias de control y su lógica de procesamiento se puede expresar en diferentes modelos o incluso en distintos lenguajes. Normalmente, esta flexibilidad no es posible en los sistemas existentes.
La unidad de abstracción y argumento de flexibilidad es similar a comparar SoA (Arquitecturas orientadas a servicios) frente a actores. Los sistemas de actor permiten más flexibilidad, ya que cada actor es esencialmente un "servicio diminuto" administrado de forma independiente. Del mismo modo, el sistema de flujo debe permitir este control específico.
Distribución
Y, por supuesto, el sistema debe tener todas las propiedades de un "buen sistema distribuido". Esto incluye:
- Escalabilidad: admite un gran número de flujos y elementos de proceso.
- Elasticidad: permite agregar o quitar recursos para aumentar o reducir en función de la carga.
- Confiabilidad: resistente a errores.
- Eficiencia: usa los recursos subyacentes de forma eficaz.
- Capacidad de respuesta: habilita escenarios casi en tiempo real.
Estos eran los requisitos para construir Orleans Streaming.
Aclaración: Orleans actualmente no admite directamente la escritura de expresiones de flujo de datos declarativas como en el ejemplo anterior. Las APIs de streaming actuales Orleans son bloques de construcción de bajo nivel, como se describe en las Orleans APIs de streaming.