Kafka no funciona de la misma manera que los framework mas comunes(ActiveMQ o RabbitMQ) por lo que no hay una forma directa de hacer lo mismo pero en este artículo voy a describir como aplicar comportamientos equivalentes.
Para comprender correctamente este articulo necesitas tener conocimientos básicos de Docker y Spring boot.
La forma mas sencilla de montar un "servidor" de Kafka es usar Docker, se puede usar el siguiente fichero de docker-compose:
docker-compose.yml
version: '3'
services:
zookeeper:
image: wurstmeister/zookeeper
ports:
- "2181:2181"
hostname: zookeeper
kafka:
image: wurstmeister/kafka
command: [start-kafka.sh]
ports:
- "9092:9092"
hostname: kafka
environment:
KAFKA_ADVERTISED_HOST_NAME: localhost
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_PORT: 9092
volumes:
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- "zookeeper"
Una vez ejecutado este fichero, ya esta disponible Kafka en el puerto 9092.
El código del productor de mensajes y de consumidor de mensajes esta en https://github.com/rumberomelo/productor-consumidor-basico
Si descargas el código y lo ejecutas (y has arrancado Kafka como indico al principio) puedes comprobar el funcionamiento mas sencillo, un productor que escribe un mensaje de texto que lee un unico consumidor. Para hacer funcionar el ejemplo solo tienes que hacer la siguiente petición:
http://localhost:9000/envia/mensaje?texto=hola
Esta petición hará que el productor escriba en el tópico de Kafka "TOPIC_EJEMPLO" el mensaje "hola". Puedes comprobar en el log del consumidor que lo ha leido ya que aparecera un mensaje como INFO 47114 --- [ntainer#0-0-C-1] com.rumberomelo.kafka.consumer.Consumer : Se ha consumido el mensaje hola.
Este ejemplo muestra como un consumidor lee un mensaje que produce un productor. Si lanzaramos un consumidor exactamente igual pueden pasar dos cosas (depende de como se configure Kafka):
- El nuevo consumidor es el unico que lee todos los mensajes de productor.
- El nuevo consumidor siempre queda a la espera (nunca lee ningun mensaje) y el viejo consumidor lee todos los mensajes.
Esto se puede comprobar en el ejemplo https://github.com/rumberomelo/productor-dos-consumidores y ver que solo un consumidor lee el mensaje. Si aplicamos un pequeño cambio y cambiamos el nombre de los grupos de cada uno de los consumidores como indican estos dibujos:
Al arrancar de nuevo los ejemplos se puede comprobar como los dos consumidores reciben en mensaje mirando el log de los consumidores. Este comportamiento es igual al tópico de frameworks como RabbitMQ o ActiveMQ.
Volvemos a dejar el nombre de los grupos como estaba. ¿Como se hace para que un mensaje lo lea uno de los consumidores (no siempre el mismo)? Se hace indicando las particiones en las que se quiere dividir el tópico. Cuando un productor escribe en un tópico que no existe (que es lo que se ha hecho al principio de este articulo) se crea automáticamente sin particiones, si tienes varias particiones entonces los consumidores se reparten dichas particiones de tal manera que cada consumidor solo lee de una de las particiones asignadas y como un mensaje se puede colocar aleatoriamente en cualquier particiones ya se ha logrado que sea un consumidor cualquiera el que lea el mensaje.
Para probarlo, se debe entrar en el contenedor de Kafka:
$ docker exec -it articulokafta_kafka_1 bash
Se puede comprobar que no hay particiones:
$ kafka-topics.sh --describe --zookeeper zookeeper:2181 --topic TOPIC_EJEMPLO
Topic:TOPIC_EJEMPLO PartitionCount:1 ReplicationFactor:1 Configs:
Topic: TOPIC_EJEMPLO Partition: 0 Leader: 1001 Replicas: 1001 Isr: 1001
Se añaden dos particiones:
$ kafka-topics.sh --alter --zookeeper zookeeper:2181 --topic TOPIC_EJEMPLO --partitions 2
Al arrancar de nuevo el ejemplo https://github.com/rumberomelo/productor-dos-consumidores y dejar el nombre de los grupos como estaban originalmente, si se hace la prueba de lanzar varios mensajes entonces se puede comprobar como a veces los lee un consumidor y a veces otro.

