Este post es el punto final a la serie de artículos en el que se muestran las diferentes maneras para la creación de soluciones para el procesamiento de flujos de datos en Kafka.

Para ello, vamos a recoger todo el conocimiento que hemos obtenido en los artículos anteriores y vamos a comparar las distintas alternativas que hemos visto, Kafka Streams DSL, Kafka Stream Processor API y ksqlDB, con la finalidad de mostrar qué alternativa puede resultar más adecuada dependiendo de la situación en la que nos podamos encontrar.

¿Qué ofrece cada alternativa?

Una de las primeras cosas que podemos estudiar es ver qué ofrece cada alternativa.

Como la serie consistía en mostrar las posibilidades dentro del ecosistema Kafka para el procesamiento de flujos de datos en tiempo real, es obvio que cada una de las tecnologías mostradas nos van a ayudar a la construcción de este tipo de aplicaciones. Sin embargo, esto no quiere decir que esto sea lo único que ofrecen.

Si bien, tanto Kafka Streams DSL y Kafka Streams Processor API fueron creados para este propósito, ksqlDB evolucionó de tal manera que también ofrece la posibilidad de implementar conectores para integrar Kafka con sistemas externos, ya que, además de estar basado en Kafka Streams, está totalmente integrado con Kafka Connect.

Teniendo esto claro, vamos a centrarnos únicamente en la parte del procesamiento en tiempo real y ver, desde distintos puntos de vista, algunos detalles que nos permitan diferenciar que ofrece técnicamente cada una de estas alternativas.

Comparemos las alternativas

A continuación, vamos a poner frente a frente las tres alternativas desde el punto de vista de infraestructura, nivel de abstracción, rendimiento y ciclo de vida.

Infraestructura

Una pregunta que nos podemos plantear a la hora de elegir entre las distintas tecnologías es la infraestructura asociada a cada una de ellas.

Como hemos comentado, Kafka Streams es una tecnología que está disponible a través de Apache Kafka.

Apache Kafka: Kafka conect, core y Kafka Streams.

Cualquier distribución de Apache Kafka suele tener disponible esta tecnología, por lo que una vez el entorno está disponible, ya tendríamos a disposición la API de Kafka Streams para poder construir aplicaciones para el procesamiento en tiempo real con DSL o Processor API a través de la librería que proporciona.

A nivel de infraestructura propia, los componentes desarrollados con Kafka Streams DSL o Processor API no dejan de ser como un servicio más, desplegándose en la plataforma de ejecución habitual (como puede ser Kubernetes). Por tanto, no requieren añadir elementos de infraestructura nuevos al ecosistema, pero sí hay que tener en cuenta la capacidad y redimensionar en caso necesario.

En el caso de ksqlDB es distinto. Si bien, su base es Kafka Streams, es un componente licenciado bajo la licencia Confluent Community License y, aunque es cierto que puede funcionar sobre un Kafka vanilla, es muy recomendable (por no decir indispensable) un entorno Confluent para su ejecución.

Confluent: Kafka Concect, Kafka Streams, Core, Schema Registry, Control Center.

Esto implica la necesidad de licencia para poder usar ksqlDB a nivel empresarial, con un costo asociado que podríamos no tener en el caso de usar otro tipo de distribuciones que no ofrecen todo lo que ofrece el ecosistema Confluent, siempre y cuando no se tenga la necesidad de hacerlo.

Además, a nivel de infraestructura propia, necesita máquinas adicionales para alojar sus componentes específicos, como el server. En la documentación de ksqlDB se puede encontrar ayuda para realizar el plan de capacidad adecuado a tus necesidades.

Entonces, ¿cuál es la mejor opción? En general, va a depender del contexto en el que nos encontremos, las necesidades y las posibilidades que tengamos.

Nivel de abstracción

Uno de los puntos claves a la hora de comparar las distintas tecnologías es su nivel de abstracción.

Si recordamos los anteriores artículos de la serie, dentro de la tecnología de Kafka Streams se tiene Processor API, con un nivel de abstracción bajo, y DSL, con un nivel de abstracción alto. Posteriormente, se presentó ksqlDB, con un nivel de abstracción muy alto respecto a Kafka Streams debido a su interfaz SQL.

Interfaz SQL de Kafka Streams

Entonces, ¿qué implica el nivel de abstracción de cada tecnología a la hora de crear las soluciones para el procesamiento de flujos de datos en tiempo real?

Es importante saber que cuanto mayor es el nivel de abstracción de una tecnología, mayor es el número de operaciones encapsuladas preparadas para ayudar a implementar las distintas aplicaciones usando dicha tecnología, facilitando en gran medida la tarea del programador. Si nos centramos en las tecnologías que hemos ido mostrando, podemos evidenciar este hecho.

Recordando la etapa de Recogida de Información de la topología implementada, existen una serie de operaciones que se realizan sobre el flujo de datos.

Flujo de datos de la recogida de la información.

Con Kafka Streams DSL, la manera de implementar estas operaciones es realmente sencillo, ya que existen funciones encapsuladas que proporciona la librería que permiten realizar dichas operaciones.

Kafka Streams DSL.

En cambio, el código implementado con Processor API es algo más complejo ya que, al tener un nivel de abstracción más bajo, no existen esas funciones encapsuladas que proporciona la librería y tenemos que implementarlas desde cero.

Código implementado con Processor API

Eso sí, ksqlDB está a otro nivel respecto a sencillez y comodidad en el código, ya que su interfaz SQL simplifica mucho las operaciones. Además, abre la posibilidad del procesamiento en tiempo real a personas con poco bagaje en los lenguajes de programación.

Procesamiento en tiempo real.

La elección de una tecnología u otra tiene impacto directo en el código implementado, ya que hay que tener en cuenta que un código más complejo puede tener impacto directo tanto en un aumento de los puntos de fallo del código y del costo de mantenimiento del proceso.

Si bien esto es algo a tener muy en cuenta, hay que tener claro que cuanto mayor es el nivel de abstracción, menor es el control que tenemos de dicha tecnología.

Usando Processor API, que aparentemente podría ser la opción menos atractiva, podemos hilar mucho más fino y llegar donde las otras abstracciones no pueden llegar, ya que nos permite controlar aspectos de mucho más bajo nivel que pueden ser necesarios en el proceso que se quiera implementar.

Por ello, aunque el nivel de abstracción resulta importante para un programador, también hay que tener en cuenta las necesidades del proceso a implementar.

Rendimiento

Otro aspecto a tener en cuenta para comparar las distintas alternativas es su rendimiento. Si bien todas las tecnologías que hemos visto tienen la misma base, Kafka Streams, sí que podemos mirar su rendimiento desde distintos puntos de vista.

Uno de los conceptos claves es el de cómo están optimizados los distintos niveles de abstracción de Kafka Streams. Si bien es cierto que distintos niveles aportan distintas operaciones, en ocasiones hay algunas que están mejor implementadas en una tecnología que en otra, como puede ser la gestión de las ventanas de tiempo que hemos visto durante el caso de uso. Tanto Kafka Streams DSL como ksqlDB tienen una operación encapsulada para gestionar dichas ventanas, pero el rendimiento de ksqlDB es mejor que el de Kafka Streams DSL.

Por otro lado, otro aspecto a tener en cuenta respecto a su rendimiento es la infraestructura de cada tecnología comentada anteriormente.

Cuando se implementa una aplicación con Kafka Streams (ya sea DSL o Processor API) lo que se hace es hacer uso de la librería que se proporciona para interactuar con la API que ofrece. Básicamente, lo que hacemos es implementar nuestra aplicación de forma externa al ecosistema Kafka para interactuar con el cluster en general, y con la tecnología Kafka Streams en particular.

Kafka Streams, ya sea DSL o Processor API.

En cambio, cuando se crea una aplicación ksqlDB no sales del ecosistema Kafka, sino que se ejecutan las sentencias SQL en el propio servidor ksqlDB para interactuar con Kafka Streams, siempre dentro del ecosistema Kafka.

Aplicación ksqlDB que ejecuta las sentencias SQL en el propio servidor ksqlDB.

¿Qué ocurre entonces? ¿Por qué esto puede afectar al rendimiento?

Con ksqlDB aprovechamos al completo todas las características del ecosistema Kafka sin tener ningún agente externo que pueda impactar en el procesamiento, al contrario que Processor API y DSL, que ya tenemos que gestionar otro tipo de cosas adicionales. Si bien es cierto que en la mayoría de los casos puede tener un impacto mínimo, sobre todo si evitamos problemas como latencias, etc., en algunos casos en los que el rendimiento es capital, hay que tener en cuenta todos estos factores.

Por otro lado, otro punto a tener en cuenta cuando se trabaja con Kafka Streams DSL o Processor API es la necesidad de almacenamiento e impacto en rendimiento que esto produce. En el caso del DSL, cuando se realizan operaciones de agregación y trabajo con ventanas, internamente se apoya en topics intermedios como almacenamiento temporal para las operaciones. Estos topics intermedios, como todos los topics, necesitan espacio de almacenamiento físico y, además, suponen gasto de recursos ya que deben ser manejados y replicados.

Ciclo de vida y experiencia de desarrollo

Para finalizar, vamos a estudiar qué ocurre en el ciclo de vida de las aplicaciones según la alternativa utilizada y la experiencia de desarrollo adquirida a través de su uso. Para ello, vamos a verlo desde distintos puntos de vista.

Desarrollo

A nivel de desarrollo encontramos diferencias significativas.

Si desarrollamos nuestros procesos usando Kafka Streams DSL o Processor API lo haremos usando Java o Scala, de forma similar a cómo desarrollamos otros muchos servicios. Además, podremos compartir las herramientas y buenas prácticas de desarrollo que ya utilizamos con el resto de servicios.

En cambio, si optamos por ksqlDB tendremos que utilizar SQL, siendo las herramientas y los IDEs más limitados.

A priori puede parecer que optar por SQL puede ser más sencillo pero, en realidad, optar por una u otra depende del conocimiento y de herramientas de las que se dispongan.

Testing

Cuando nos centramos en la parte de comprobar que los procesos que implementamos cumplan con los requisitos necesarios, también hay que tener en cuenta la naturaleza tanto de Kafka Streams como de ksqlDB.

En el caso de usar Kafka Streams DSL o Processor API, la estrategia y herramientas de testing es la misma que con cualquier otra aplicación Java o Scala. En el caso de implementar tests de integración, disponemos tanto de la posibilidad de usar un Kafka embebido o Testcontainers, que nos permiten, entre otras cosas, simular escenarios de alta carga o latencias.

Por otro lado, si optamos por ksqlDB, las opciones se limitan a ksql-test-runner, centrándose prácticamente en tests unitarios de los scripts SQL. Realmente, es un enfoque muy válido, porque toda la operativa se inicia y se crea en topics de Kafka, por lo que si trabajamos bien los mensajes del topic de entrada y los de salida, estamos garantizando que no habrá problemas en ese proceso. El resto de componentes que interactúan con la entrada o salida del proceso ksqlDB, no necesitan realmente dicho proceso, simplemente los topics y los mensajes de entrada y de salida.

CI/CD

Otro aspecto importante es cómo podemos integrar las distintas alternativas en nuestros flujos de CI/CD.

En el caso de Kafka Streams DSL o Processor API, no hay diferencia con el resto de componentes desarrollados con Java o Scala, ni en construcción, ni en empaquetado, ni en despliegue, ni en monitorización. Se puede utilizar el mismo sistema de CI/CD que usamos para otro tipo de aplicaciones.

En cambio, si optamos por ksqlDB, tenemos que crear un modelo de CI/CD ad hoc, similar al que podemos tener con los scripts asociados a una base de datos con soluciones como Flyway. Aunque desde la versión 0.17.0 de ksqlDB, disponemos de una nueva herramienta, ksql-migrations, que nos permite disponer de versionado de nuestros scripts. De esta forma, podremos tener nuestros scripts y sus evoluciones en una herramienta de control de versiones como Git y, con ksql-migrations, poder integrarlo en una herramienta de CI/CD para ser desplegados y permitiendo operaciones de rollback en caso de ser necesario.

¿Con cuál nos quedamos?

Entonces, visto lo visto en los puntos anteriores y, teniendo en cuenta que hay tanto beneficios como algunos inconvenientes en cada una de las tecnologías, ¿con cuál nos quedamos?

A esta pregunta, respondemos con otra pregunta, ¿por qué debes quedarte con alguna en particular?

La idea detrás de lo que hemos mostrado es que tenemos un abanico de herramientas optimizadas con Kafka que nos permite procesar flujos de mensajes en tiempo real. Esto no quiere decir que una herramienta sea peor o mejor que otra, sino que son distintas formas que tenemos para adaptarnos a nuestras necesidades.

Además, una parte importante a tener en cuenta es que la elección de una herramienta no excluye a las otras, es decir, podemos combinar distintas herramientas dentro de un mismo flujo de procesamiento para optimizar y facilitar la creación de este tipo de aplicaciones. De hecho, suele ser muy común una estrategia heterogénea a la hora de implementar un proceso de este tipo.

Con este artículo cerramos la serie dedicada al procesamiento de mensajes en tiempo real dentro del ecosistema Kafka. Esperamos que os haya gustado y que os sirvan de ayuda y modelo para construir vuestras soluciones.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.