在nodejs中接入kafka生产消费消息

2,013 阅读3分钟

kafak的安装与启动

  • mac系统下直接使用如下命令安装

brew install kafka

安装完毕后,应用程序目录:

/usr/local/Cellar/kafka/2.0.0

配置文件目录

/usr/local/etc/kafka/

zookeeper配置文件在此目录中,可以看到zookeeper默认端口为2181

kafka启动并发布创建主题

  1. 进入目录程序主目录,先启动zookeeper,再启动kafka,&为后台运行
zookeeper-server-start /usr/local/etc/kafka/zookeeper.properties &
kafka-server-start /usr/local/etc/kafka/server.properties &
  1. 停止运行的命令
bin/kafka-server-stop
bin/zookeeper-server-stop
  1. 进入bin目录,创建主题topic,使用默认zookeeper以及默认端口即可,分区设置为1个,备份因子1个,主题名称topic-test-one
./kafka-topics --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic topic-test-one

通过如下命令可查看所有主题以及主题对应的属性

展示topic

./kafka-topics --list --zookeeper localhost:2181

描述topic

.kafka-topics --describe --zookeeper localhost:2181 --topic topic-test-one

node接入kafka

模块: kafka-node

默认一个分区模式

首先创建生产者:

var kafka = require('kafka-node'),
Producer = kafka.Producer,
client = newkafka.KafkaClient({kafkaHost:'192.168.20.59:9092'});
/**
 * 定义生产类
 * partitionerType 定义
 * 0:默认模式 只产生数据在第一个分区
 * 1:随机分配,在分区个数内,随机产生消息到各分区
 * 2:循环分配,在分区个数内,按顺序循环产生消息到各分区
*/
var producerOption = {
requireAcks:1,
ackTimeoutMs:100,
partitionerType:0//默认为第一个分区
};
var producer = newProducer(client,producerOption);
  console.log(producer)
  /**
   * TOPIC的创建需要在命令行进行创建,以便指定分区个数以及备份个数
   * PS:kafka-node的创建topic不行,不能创建分区
   * 产生消息,如果不指定partition
   * 则根据 partitionerType 的值来指定发送数据到哪个分区
   * 我们创建的topic-test-one只有一个分区,所以只能产生数据到第1个分区(下标0),否则不会生产数据
   */
  functiongetPayloads(){
  return [
          {topic:"topic-test-one",messages:					[JSON.stringify({"name":"jack","age":"120"})],partition:0}
      ];
}
producer.on("ready",function(){
console.log(getPayloads())
setInterval(function(){
producer.send(getPayloads(),function(err,data){
  console.log(data)
  if(!err){
  console.log("send message complete!data:"+JSON.stringify(data),newDate());
              }
  else {
  console.log(err)
              }
          });
       },1000);
});
producer.on('error', function (err) {console.log("send message error!\r\n"+err);})
消费者定义:
constkafka = require('kafka-node');
constclient = newkafka.KafkaClient({ kafkaHost:'192.168.20.59:9092' });
/**
 * 定义消费参数
 */
var consumerOption = {
  groupId:"topic-test-one",
  autoCommit:true
};
/**
 * 定义consumer,指定从分区0获取数据
 */
constconsumer = newkafka.Consumer(client, [
  { topic:'topic-two',partition:0}
],consumerOption);
/**
 * 监听消费数据
 */
consumer.on('message', function (message) {
  varinfo = message.value;
	console.log("receive info from kafka:"+info,newDate());
});
consumer.on('error', function (message) {
	console.log('kafka连接错误,message:'+message);
});

运行看效果:

随机分区模式

重新创建topic-test-two,分区为2

/kafka-topics --create --zookeeper localhost:2181 --replication-factor 1 --partitions 2 --topic 
topic-test-two

将生产者producerOption的partitionerType设置为1,以及getPayloads()方法中的partition给删除

var producerOption = {
  requireAcks:1,
  ackTimeoutMs:100,
  partitionerType:1//默认为第一个分区
};
var producer = newProducer(client,producerOption);
console.log(producer)
/**
 * TOPIC的创建需要在命令行进行创建,以便指定分区个数以及备份个数
 * PS:kafka-node的创建topic不行,不能创建分区
 * 产生消息,如果不指定partition
 * 则根据 partitionerType 的值来指定发送数据到哪个分区
 * 我们创建的topic-test-one只有一个分区,所以只能产生数据到第1个分区(下标0),否则不会生产数据
 */
function getPayloads(){
  return [
          {topic:"topic-three",messages:[JSON.stringify({"name":"jack","age":"120"})]}
      ];
}

可以看到生产者分别生产分区0和分区1的数据,且具有随机性

同时创建两个consumer,分别设置取值从partition0和partition1,观察效果:

consumer1.js

const consumer = newkafka.Consumer(client, [
  { topic:'topic-test-two',partition:0}
],consumerOption);
consumer2.js
const consumer = newkafka.Consumer(client, [
  { topic:'topic-test-two',partition:1}
],consumerOption);

而消费者分别从0分区和1分区获取数据,从时间上可以看出,他们消费的是不同分区的数据

顺序分区模式

此模式同随机分区模式,只需要设置partitionerType为2即可.