Kafka在Windows上的使用
1.下载安装并启动Zookeeper
Kafka的运行依赖于Zookeeper,简单点讲:ZooKeeper是一个集中服务,用于维护配置信息,命名,提供分布式同步和提供组服务。它和Kafka一样,都是Apache旗下的组件。如何下载都不赘述,本次演示用的软件都会在底部源代码给出。
下载之后,得到类似zookeeper-3.4.8.zip这样的文件夹,我这里用了一个比较稳定的版本来演示。
之后解压,得到zookeeper-3.4.8文件夹,可以把这个文件夹放到自己的常用软件安装路径下,打开文件夹,再进入conf文件夹,复制zoo_sample.cfg文件到当前文件夹下,重命名为zoo.cfg,如图:
之后进入zookeeper-3.4.8\bin目录,双击zkServer.cmd,启动Zookeeper服务,成功启动之后,可以看到服务占用了2181端口:
2.下载安装并启动Kafka
同样是在Apache上面下载Kafka,下载之后得到kafka_2.11-1.1.0.tgz的压缩包,解压后为了方便,也是可以放到常用软件的安装路径下,打开一个命令行,进入Kafka如下的安装目录:kafka_2.11-1.1.0\bin\windows,之后运行kafka-server-start ../../config/server.properties,用Kafka的server.properties文件来启动Kafka,成功启动之后,Kafka会占用9092端口,与RabbitMQ类似,Kafka也提供了相应的API供我们调用,只不过Kafka没有像RabbitMQ那样比较直观的后台管理界面
3.编写消息生产者和消息消费者
新建一个简单java的maven项目hello-kafka,在pom.xml中引入Kafka的依赖:
<dependencies>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
之后创建org.init.springcloud包,在包下新建SendMessage.class类,用于消息的发送,详细步骤已经写在注释里了:
package org.init.springcloud;
import java.util.Properties;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
public class SendMessage {
public static void main(String[] args) {
//初始化配置信息
Properties properties = new Properties();
properties.put("bootstrap.servers", "localhost:9092");
//数据key的序列化处理类
properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
//数据value的序列化处理类
properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
//创建生产者
Producer<String,String> producer = new KafkaProducer<String,String>(properties);
//生成一条新的记录,前一个参数是Topic的名称,后面两个对应数据的键值
ProducerRecord<String,String> record = new ProducerRecord<String,String>("hello-topic","username","spirit");
//发送记录
producer.send(record);
//关闭消息生产者
producer.close();
}
}
运行main()方法,发送我们的消息。之后新开一个命令行,还是去到kafka_2.11-1.1.0\bin\windows路径下,运行命令:kafka-topics --list --zookeeper localhost:2181,查看Kafka上面有哪些Topic,可以看到我们刚刚发送的hello-topic,已经在Kafka上了:
之后创建一个消息消费者ReceiveMessage.class类来接收消息,代码里写明了详细步骤:
package org.init.springcloud;
import java.util.Arrays;
import java.util.Properties;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
public class ReceiveMessage {
public static void main(String[] args) {
//初始化配置信息
Properties properties = new Properties();
properties.put("bootstrap.servers", "localhost:9092");
//指定消费者组(必须!)
properties.put("group.id", "hello-kafka");
//数据key的反序列化处理类
properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
//数据value的反序列化处理类
properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
//创建消费者
@SuppressWarnings("resource")
Consumer<String,String> consumer = new KafkaConsumer<String,String>(properties);
//订阅hello-topic的信息
consumer.subscribe(Arrays.asList("hello-topic"));
//读取消息
while(true){
ConsumerRecords<String,String> records = consumer.poll(50);
for (ConsumerRecord<String, String> record : records) {
System.out.println("消息的key为:"+record.key()+",消息的值为:"+record.value());
}
}
}
}
之后运行main()方法,可以看到控制台输出了我们的信息:
消费者组的概念
我们刚刚在创建消费者的时候,设置了一个消费者组的东西,也就是group.id,它是用于分布式或者集群的。如上图,假设我们有两个消费者:A和B,如果A和B都拥有同一个group.id,那么,当Kafka上面有一条消息广播出来的时候,A和B只有其中一个能接收到消息,这就实现了一个负载的效果;但是如果A和B是属于不同的消费者组,那么当Kafka广播消息的时候,两个消费者A和B就都能接收到消息了。
拷贝ReceiveMessage类生成ReceiveMessageB类,不修改其他信息,只是修改两者的打印信息,对于ReceiveMessage:
System.out.println("消费者A,消息的key为:"+record.key()+",消息的值为:"+record.value());
对于ReceiveMessageB:
System.out.println("消费者B,消息的key为:"+record.key()+",消息的值为:"+record.value());
同时启动这两个类,之后运行SendMessage的main()方法,查看ReceiveMessage和ReceiveMessageB的控制台输出:
可以看到只有ReceiveMessage是输出了信息的,之后我们修改ReceiveMessageB的消费者组:
//指定消费者组(必须!)
properties.put("group.id", "hello-kafka-b");
保存之后,重启ReceiveMessage和ReceiveMessageB,运行SendMessage的main()方法,查看ReceiveMessage和ReceiveMessageB的控制台输出:
最后,大家有什么不懂的或者其他需要交流的内容,也可以进入我的QQ讨论群一起讨论:654331206
Spring Cloud系列:
Spring Cloud服务管理框架Eureka简单示例(三)