Spring Cloud Functions, Stream, Rabbit MQ y Kafka - nelsonortfan/MicroDockerSpringBoot GitHub Wiki

Spring Cloud Functions

Comenzamos creando el siguiente proyecto message en Spring Initializr con las siguientes características y agregando la dependencia de Function Spring Cloud:

Luego de descomprimimos este proyecto y lo agregamos a los demas microservicios. Dentro de este creamos el paquete dto y en el el Record AccountsMsgDto:

Creamos otro paquete llamado functions y en el la clase MessageFunctions con los siguientes Beans haciendo uso de las Functions que ofrece Java. En el primer Bean la entrada sera un objeto del tipo AccountsMsgDto al igual que su salida, mientras que en el segundo Bean la entrada sera AccountsMsgDto y la salida sera un Long:

Estos Beans son para mostrar que los mensajes se han enviado correctamente.

En el archivo pom.xml agregaremos la dependencia de Spring cloud starter functions web que nos permitira que nuestros Beans sean expuestos como endpoints REST que se pueden consultar:

Agregamos 2 breakpoints en los logs para que podamos ver los resultados:

Luego abrimos la Collection de Postman y hacemos las peticiones REST cuyos endpoints son iguales a los nombres de los Beans:

Si intentamos enviar la tercera petición de la Collection fallara ya que no esta configurado para que los 2 Beans funcionen como una sola lógica:

Para arreglarlo, vamos al archivo application.yml y definimos el endpoint bajo la propiedad spring.cloud.function.definition, también cambiamos el puerto de inicio para que no entre en conflicto con el microservicio Accounts:

Iniciamos de nuevo el microservicio y esta vez funcionara sin inconveniente:

Vemos también los Logs en consola y se visualizan los mensajes:

Spring Cloud Stream

A continuación usaremos la librería Spring Cloud Stream, la cual nos permitirá conectarnos a Brokers como Rabbit MQ o Kafka de manera sencilla y sin tanta configuración. Adicional, internamente trabaja con Spring Cloud Function, razón por la cual retiramos las anteriores librerías del archivo pom.xml. También agregamos la dependencia que nos permitirá conectarnos a Rabbit MQ:

De igual manera añadimos el plugin para poder crear después la imagen de Docker:

Luego, en el archivo application.yml bajo la propiedad de spring.cloud.stream agregaremos los bindings y le daremos nombres para poder identificar cuales serán de entrada y cuales de salida para enviar los mensajes al broker, al igual que los parámetros de conexión hacia el broker de Rabbit MQ:

De igual manera, en el microservicio Accounts agregamos las dependencias para usar Spring Cloud Stream y conectarnos a Rabbit MQ:

En ese mismo microservicio, en el paquete dto creamos el siguiente Record:

Configuramos el archivo application.yml para establecer el bind de salida al cual enviaremos el mensaje:

Y las propiedades de conexión a Rabbit MQ:

Modificamos la clase AccountServiceImpl para poder primero log de los mensajes y segundo un Stream que nos ayudara a enviar los mensajes. Modificamos el código de la clase para crear una nueva Account para que se envíe al broker, incluso un método privado que hace eso:

Rabbit MQ

Vamos a la pagina de Rabbit MQ para poder descargar la imagen y ejecutarla desde nuestro Docker:

El comando es:

docker run -d -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:4-management

Veremos que se crea la imagen:

Iniciamos los microservicios en el orden que se ve la imagen (No se incluye LOANS ni CARDS por tema de simplicidad):

Previo a esto, iniciamos el servidor de Keycloak también en el contenedor.

Ingresamos a la consola administradora de Rabbit MQ con usuario y password guest respectivamente:

Veremos los Exchanges creados por nuestros microservicios, al igual que los Queues y streams:

Luego de todo el proceso de obtener el Token y demás, enviamos la petición para crear una nueva Account:

Veremos que en Rabbit MQ se ve que hubo movimiento con el mensaje enviado:

Veremos la consola de logs de Accounts evidenciando que se envió el mensaje:

Y en la consola de Message que se recibió:

Hacemos la configuración necesaria para enviar el mensaje de respuesta desde Message hacia Accounts. Algo importante es que en la tabla de Accounts se agrega un nuevo campo llamado communication_SW de tipo boolean que indica si se recibió el mensaje de respuesta. Se agrega también el binding de entrada y veremos en Rabbit MQ la siguiente configuración:

Detenemos el servicio de Message y le ponemos break points. Lo iniciamos en modo Debug:

Desde Postman enviamos de nuevo una petición para crear un Account y vemos que aun no se recibe el mensaje de respuesta dado los break points ya que en la tabla el campo boolean esta en FALSE:

Ejecutamos step by step el servicio Message (botón similar a un Play-Pause cerca al botón de Stop) y veremos los mensajes en consola:

Si revisamos de nuevo la tabla, veremos que el campo boolean ahora es TRUE, confirmando que se recibió el mensaje y la comunicación fue exitosa en los 2 sentidos:

Contenedores Docker con Rabbit MQ

Ahora procedemos a crear las imágenes de Docker incluyendo el broker de Rabbit MQ. Creamos las imágenes de los microservicios que tenemos hasta el momento y de Message con la versión S13 y las enviamos al Docker Hub:

Procedemos a modificar el archivo docker-compose.yml para agregar el servicio de Rabbit MQ:

En el servicio de Accounts, agregamos la dependencia hacia el servicio de Rabbit MQ:

Igualmente agregamos el servicio de Message:

Procedemos a crear los contenedores de los servicios del archivo de docker compose:

Hacemos las pruebas hechas antes con previa configuración de nuevo de Keycloat en la nueva imagen creada y vemos los logs de Accounts y Message que evidencian el correcto funcionamiento de todo:

Kafka Server

Vamos a la pagina de Kafka y buscamos el comando para bajar la imagen:

Arrancamos el contenedor:

Veremos que esta imagen ha arrancado con la ayuda de kraft que es el reemplazo de Zookeeper:

En Intellij instalamos el plugin kafkalytic que nos permitira ver el estado de Kafka:

Tanto en Accounts como en Message quitamos la dependencia hacia Rabbit MQ y colocamos la de Kafka:

De igual maneran en los arrchivos application.yml de ambos microservicios quitamos la propiedad de conexion hacia Rabbit MQ y colocamos la de Kafka aprovechando que hace parte de Spring Cloud Stream:

Probamos en Intellij la conexion hacia Kafka y es exitosa:

Veremos los consumers y los topics creados:

Iniciamos el servicio de Message en modo Debug con un breakpoint en el log como lo hemos hecho antes:

Si hacemos de nuevo la prueba desde Postman para Accounts y vamos haciendo el debug en Message, veremos que el mensaje llega:

Y validamos en la base de datos que el campo booleano es True:

Contenedores Docker con Kafka

Para este punto creamos de nuevo las imagenes pero con el tag S14 y las enviamos a Docker Hub. Modificamos de nuevo el archivo docker-compose en el cual removemos el servicio de Rabbit MQ y agregamos el de Kafka, al igual que actualizamos la dependencia de los servicios Accounts y Message hacia el broker, esta vez hacia kafka. Los cambios se pueden ver en el codigo en la version V.9.1 y proceddemos a crear la imagen:

Procedemos hacer de nuevo todas las pruebas y vemos que son exitosas al revisar los Logs de los microservicios Accounts y Message:

Procedemos a destruir los contenedores creados: