Trabajo con Apache Kafka en Node.js usando la biblioteca KafkaJS
\n\nApache Kafka es una plataforma distribuida para transmisión de eventos en flujo, que se ha convertido en el estándar de facto para construir sistemas de mensajería de alta carga. En el ecosistema de Node.js, una de las bibliotecas más populares y estables para interactuar con Kafka es KafkaJS. Es un cliente moderno, completamente asíncrono, escrito en JavaScript puro, que soporta todas las capacidades clave de Kafka: productores, consumidores, grupos de consumidores, gestión de offsets y transacciones.
\n\nEn este artículo, analizaremos en detalle cómo instalar KafkaJS, configurar la conexión a un clúster de Kafka, enviar y leer mensajes, y también veremos las mejores prácticas para trabajar con esta biblioteca en un entorno de producción.
\n\nInstalación y configuración de KafkaJS
\n\nLa instalación de la biblioteca se realiza con el gestor de paquetes estándar npm:
\n\nnpm install kafkajs\n\nDespués de la instalación, es necesario crear un cliente especificando las direcciones de los brokers y un identificador de cliente. Ejemplo de configuración mínima:
\n\nconst { Kafka } = require('kafkajs');\n\nconst kafka = new Kafka({\n clientId: 'my-app',\n brokers: ['localhost:9092']\n});\n\nPara entornos de producción, se recomienda especificar varios brokers separados por comas para garantizar la tolerancia a fallos, así como configurar SSL y autenticación SASL:
\n\nconst kafka = new Kafka({\n clientId: 'my-production-app',\n brokers: ['broker1:9092', 'broker2:9092', 'broker3:9092'],\n ssl: true,\n sasl: {\n mechanism: 'scram-sha-256',\n username: 'myuser',\n password: 'mypassword'\n }\n});\n\nProductor: envío de mensajes a un tópico
\n\nEl productor se encarga de publicar mensajes en un tópico de Kafka especificado. KafkaJS ofrece dos modos de funcionamiento del productor: simple (send) y transaccional (para entrega exacta). Veamos un ejemplo básico de envío de un mensaje:
\n\nconst producer = kafka.producer();\n\nasync function sendMessage() {\n await producer.connect();\n\n await producer.send({\n topic: 'test-topic',\n messages: [\n { key: 'user1', value: '¡Hola Kafka desde Node.js!' },\n { key: 'user2', value: JSON.stringify({ orderId: 123, amount: 2500 }) }\n ]\n });\n\n await producer.disconnect();\n}\n\nsendMessage().catch(console.error);\n\nPuntos clave:
\n- \n
- topic — nombre del tópico al que se envía el mensaje. \n
- messages — arreglo de objetos, cada uno puede contener
key(opcional) yvalue(cadena o Buffer). \n - Se recomienda llamar a
producer.connect()una sola vez al iniciar la aplicación y reutilizar la conexión. \n
Para mejorar el rendimiento en producción, use un pool de conexiones y la configuración de acks:
const producer = kafka.producer({\n allowAutoTopicCreation: false,\n transactionTimeout: 30000\n});\n\nawait producer.send({\n topic: 'orders',\n messages: [{ value: 'Nuevo pedido' }],\n acks: -1 // Esperar confirmación de todas las réplicas\n});\n\nConsumidor: lectura de mensajes de un tópico
\n\nEl consumidor permite leer mensajes de uno o varios tópicos. El concepto más importante son los grupos de consumidores (consumer groups), que proporcionan balanceo de carga y garantizan que cada mensaje sea procesado solo por un consumidor del grupo.
\n\nconst consumer = kafka.consumer({ groupId: 'my-group' });\n\nasync function consumeMessages() {\n await consumer.connect();\n await consumer.subscribe({ topic: 'test-topic', fromBeginning: true });\n\n await consumer.run({\n eachMessage: async ({ topic, partition, message }) => {\n console.log({\n partition,\n offset: message.offset,\n key: message.key.toString(),\n value: message.valu