Enviando mensajes entre servicios con Kafka

0
9713
Varios buzones de correo

Índice de contenidos

  1. Entorno
  2. Introducción
  3. Añadir Kafka a nuestro proyecto
  4. Preparando el proyecto
  5. Productor
  6. Consumidor
  7. Crear un controlador REST
  8. Conclusiones

1. Entorno

Este tutorial se ha redactado utilizando el siguiente entorno para el código de ejemplo:

  • MackBook Pro Retina 15″
  • 2,5 Ghz Intel Core i7
  • 16GB RAM
  • macOS Catalina 10.15.6

2. Introducción

Kafka es una solución a la necesidad de enviar información entre diferentes entidades, permitiendo publicar, almacenar y procesar diferentes flujos de registros y poder suscribirse a los que uno necesite, en tiempo real.

Kafka es muy utilizado en microservicios, para poder compartir datos entre ellos. Explicaremos esto con un sencillo ejemplo:

Imaginemos que tenemos dos microservicios muy pequeños, uno se encarga de registrar los usuarios (Microservicio A) y otro se encarga de actualizar la información en base de datos (Microservicio B). Esto es un ejemplo, obviamente podría ir en un solo servicio.

Por tanto, cuando el usuario se registra, A tiene que informar a B con los datos para que los almacene en base de datos, pero los microservicios son totalmente independientes, entonces, ¿cómo hacemos esto? Lo que hace A, es producir un mensaje (evento) a través de un canal (tópico), y este mensaje es leído por todos los que estén escuchando el canal (consumidores), el mensaje será leído cuando B pueda y mientras A puede seguir con sus tareas, de esta forma existe comunicación y de forma asíncrona.

3. Añadir Kafka a nuestro proyecto

Bueno, para este tutorial tendremos un proyecto de Spring Boot con Java, y para añadir Kafka a nuestro proyecto basta con añadir la siguiente dependencia:

<dependency>
   <groupId>org.springframework.kafka</groupId>
   <artifactId>spring-kafka</artifactId>
</dependency>

4. Preparando el proyecto

Ahora vamos a ver lo que es un tópico y un mensaje, y a preparar el proyecto.

Un tópico es el canal por el cual circula la información, los microservicios solo podrán «escuchar» mensajes que circulen por el tópico al que están subscritos.

Y un mensaje, es la información que transmitimos. En nuestro ejemplo anterior, sería la información del usuario, por ejemplo.

Para comenzar, creamos una clase de Java, llamada User.

public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

Ahora nos faltaría por configurar Kafka a través del fichero de configuración application.yml.

server:
  port: 9000
spring:
  kafka:
    consumer:
      bootstrap-servers: localhost:9092
      group-id: group_id
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
    producer:
      bootstrap-servers: localhost:9092
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer

Aquí definimos las propiedades para Kafka, el keyvalue-deserializer nos permiten especificar el deserializador para la clave y valor almacenados en el tópico de Kafka, en este ejemplo usaremos los que usa Kafka.

5. Productor

Llegó la hora de enviar mensajes, así que para ello tendremos que crear un productor. Vamos a definir una clase llamada Producer, con el estereotipo de @Service, e inyectaremos la dependencia de KafkaTemplate, e implementaremos el método sendMessage, que nos permitirá enviar el mensaje por el tópico que deseemos. Quedaría así.

@Service
public class Producer {
    private static final Logger logger = LoggerFactory.getLogger(Producer.class);
    private static final String TOPIC = "users";

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    public void sendMessage(String message) {
        logger.info(String.format("#### -> Producing message -> %s", message));
        this.kafkaTemplate.send(TOPIC, message);
    }
}

Y esto es todo por el lado del productor, muy sencillo.

6. Crear un consumidor

Para probar que esto funcione necesitaremos un consumidor, para ello crearemos una clase llamada Consumer, y al igual que el productor, con la anotación de @Service.

Aquí lo importante es la etiqueta strong>@KafkaListener</strong, que le indicará a Kafka cuál es el método con que tiene que procesar la información que le llegue por un tópico y groupId particulares. Con esta etiqueta decimos que estamos subscritos a dicho tópico.

Quedaría así:

@Service
public class Consumer {
    private final Logger logger = LoggerFactory.getLogger(Producer.class);

    @KafkaListener(topics = "users", groupId = "group_id")
    public void consume(String message) throws IOException {
        logger.info(String.format("#### -> Consumed message -> %s", message));
    }
}

7. Crear un controlador REST

Ahora sólo nos queda crear un endpoint, para que a partir de la llamada a nuestro servicio se desencadene el envío del mensaje. Vamos a crear algo simple.

@RestController
@RequestMapping(value = "/kafka")
public class KafkaController {
    private final Producer producer;

    @Autowired
    KafkaController(Producer producer) {
        this.producer = producer;
    }

    @PostMapping(value = "/publish")
    public void sendMessageToKafkaTopic(@RequestParam("message") String message) {
        this.producer.sendMessage(message);
    }
}

De esta forma ya estaría todo, cuando despleguemos nuestra aplicación y vayamos al endpoint /publish, se enviará el mensaje que pasemos por parámetro, y lo podremos ver en la consola a través de los logs.

8. Conclusiones

Y de esta forma concluimos el tutorial, tal como hemos visto, utilizar Kafka es realmente sencillo, y nos ayudará en nuestros futuros desarrollos, espero que te haya gustado el tutorial 🙂

Hasta la próxima.

 

 

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad