Java实现Kafka生产消费
Kafka核心API
Kafka有四个核心Api
- producer API发布消息到1个或多个topic
- consumer API来订阅1个或多个topic,并处理产生的消息
- streams API充当一个流处理器,从1个或多个topic消费输入流,并产生一个输出流或多个topic,有效地将输入流转换到输出流
- connect API允许构建或运行可重复使用的生产者或消费者,将topic链接到现有的应用程序或数据系统
开发准备
开发工具Java,使用IDEA集成环境,构建工具Maven
Maven的依赖如下
<dependencies>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka_2.11</artifactId>
<scope>provided</scope>
<version>0.10.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>0.10.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-streams</artifactId>
<version>0.10.1.0</version>
</dependency>
</dependencies>
Kafka Producer
配置文件信息
Properties pros = new Properties();
pros.put("bootstrap.servers","bigdata-hadoop-data--1.novalocal:6667");//Kafka的地址
pros.put("acks","all");/*消息的确认机制,默认值为0 acks=0:生产者不会等待Kafka响应 acks=1:Kafka会把这条消息写到本地日志文件中,但是不会等待集群中其他机器的成功响应
acks=all:这个配置意味着leader会等待所有的follows同步完成。这个确保消息不会丢失,除非Kafka集群中的所有机器挂掉。这是最强的可用性保证*/
pros.put("retries",0);//配置为大于0的值的话,客户端会在消息发送失败时重新发送。
pros.put("batch.size",16384);//当多条消息需要发送到同一个分区时,生产者会尝试合并网络请求。这会提高client和生产者的效率。
pros.put("key.serializer", StringSerializer.class.getName());
pros.put("value.serializer",StringSerializer.class.getName());
pros.put("sasl.kerberos.service.name", "kafka");
pros.put("security.protocol", "SASL_PLAINTEXT");
pros.put("sasl.mechanism", "GSSAPI");
pros.put("sasl.kerberos.service.name", "kafka");
pros.put("security.protocol", "SASL_PLAINTEXT")
pros.put("sasl.mechanism", "GSSAPI");
👆这是带有Kerberos认证的配置,如果集群不带Kerberos认证就不需要这个配置
生产者生产数据代码如👇
producer.send(new ProducerRecord<String,String>(topic,"Message",messageStr));
Kafka Consumer
bootstrap.servers: kafka的地址。
group.id:组名 不同组名可以重复消费。例如你先使用了组名A消费了kafka的1000条数据,但是你还想再次进行消费这1000条数据,并且不想重新去产生,那么这里你只需要更改组名就可以重复消费了。
enable.auto.commit:是否自动提交,默认为true。
auto.commit.interval.ms: 从poll(拉)的回话处理时长。
session.timeout.ms:超时时间。
max.poll.records:一次最大拉取的条数。
auto.offset.reset:消费规则,默认earliest 。
earliest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费。
latest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据 。
none: topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常。
key.serializer: 键序列化,默认org.apache.kafka.common.serialization.StringDeserializer。
value.deserializer:值序列化,默认org.apache.kafka.common.serialization.StringDeserializer
配置信息
Properties pros = new Properties();
pros.put("bootstrap.servers","bigdata-hadoop-data--1.novalocal:6667");
pros.put(ConsumerConfig.GROUP_ID_CONFIG,GROUPID);//指定消费组,消费组可以不存在
//pros.put("groupID",GROUPID);
pros.put("enable.auto.commit", "true");
pros.put("auto.commit.interval.ms", "1000");
pros.put("session.timeout.ms", "30000");
pros.put("auto.offset.reset", "earliest");
pros.put("key.deserializer", StringDeserializer.class.getName());
pros.put("value.deserializer", StringDeserializer.class.getName());
pros.put("sasl.kerberos.service.name", "kafka");
pros.put("security.protocol", "SASL_PLAINTEXT");
pros.put("sasl.mechanism", "GSSAPI");
pros.put("sasl.kerberos.service.name", "kafka");
pros.put("security.protocol", "SASL_PLAINTEXT");
pros.put("sasl.mechanism", "GSSAPI");
这三条同producer
需要订阅一个topic
consumer.subscribe(Arrays.asList(topic));
订阅之后,再从中拉取数据
ConsumerRecords<String, String> msgList=consumer.poll(1000);
完整代码如下
生产者
package com.lwm.kafka;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;
import java.util.Properties;
public class KafkaProducerTest implements Runnable{
private final KafkaProducer<String, String> producer;
private final String topic;
public KafkaProducerTest(String topicName) {
//System.setProperties("java.security.auth.login.config","/usr/hdp/current/kafka-broker/config/kafka_jaas.conf");
//配置文件
Properties pros = new Properties();
pros.put("bootstrap.servers","bigdata-hadoop-data--1.novalocal:6667");//Kafka的地址
pros.put("acks","all");/*消息的确认机制,默认值为0 acks=0:生产者不会等待Kafka响应 acks=1:Kafka会把这条消息写到本地日志文件中,但是不会等待集群中其他机器的成功响应
acks=all:这个配置意味着leader会等待所有的follows同步完成。这个确保消息不会丢失,除非Kafka集群中的所有机器挂掉。这是最强的可用性保证*/
pros.put("retries",0);//配置为大于0的值的话,客户端会在消息发送失败时重新发送。
pros.put("batch.size",16384);//当多条消息需要发送到同一个分区时,生产者会尝试合并网络请求。这会提高client和生产者的效率。
pros.put("key.serializer", StringSerializer.class.getName());
pros.put("value.serializer",StringSerializer.class.getName());
pros.put("sasl.kerberos.service.name", "kafka");
pros.put("security.protocol", "SASL_PLAINTEXT");
pros.put("sasl.mechanism", "GSSAPI");
this.producer = new KafkaProducer<String,String>(pros);
this.topic = topicName;
}
@Override
public void run() {
int messageNo = 1;
try{
for(;;){
//发送的信息
String messageStr = "你好,这是第"+messageNo+"条数据";
//生产数据
producer.send(new ProducerRecord<String,String>(topic,"Message",messageStr));//
System.out.println("发送的信息:"+messageStr);
/*if(messageNo%10==0){
System.out.println("发送的信息:"+messageStr);
}*/
if (messageNo%10==0){
System.out.println("成功发送了"+messageNo+"条");
break;
}
messageNo++;
}
}catch (Exception e){
e.printStackTrace();
}finally {
producer.close();
}
}
public static void main(String[] args){
KafkaProducerTest test = new KafkaProducerTest("second");
Thread thread = new Thread(test);
thread.start();
}
}
消费者
package com.lwm.kafka;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;
import java.util.Arrays;
import java.util.Properties;
public class KafkaConsumerTest implements Runnable{
private final KafkaConsumer<String,String> consumer;
private ConsumerRecords<String,String> msgList;
private final String topic;
private static final String GROUPID = "second_1";
public KafkaConsumerTest(String topicName) {
Properties pros = new Properties();
pros.put("bootstrap.servers","bigdata-hadoop-data--1.novalocal:6667");
pros.put(ConsumerConfig.GROUP_ID_CONFIG,GROUPID);
//pros.put("groupID",GROUPID);
pros.put("enable.auto.commit", "true");
pros.put("auto.commit.interval.ms", "1000");
pros.put("session.timeout.ms", "30000");
pros.put("auto.offset.reset", "earliest");
pros.put("key.deserializer", StringDeserializer.class.getName());
pros.put("value.deserializer", StringDeserializer.class.getName());
pros.put("sasl.kerberos.service.name", "kafka");
pros.put("security.protocol", "SASL_PLAINTEXT");
pros.put("sasl.mechanism", "GSSAPI");
this.consumer = new KafkaConsumer<String, String>(pros);
this.topic = topicName;
this.consumer.subscribe(Arrays.asList(topic));
}
@Override
public void run() {
int messageNo = 1;
System.out.println("---------开始消费---------");
try{
for(;;){
msgList = consumer.poll(1000);
if(null!=msgList&&msgList.count()>0){
for (ConsumerRecord<String,String > record : msgList){
System.out.println(messageNo+"=======receive: key = " + record.key() + ", value = " + record.value()+" offset==="+record.offset());
/*if (messageNo%10==0){
System.out.println(messageNo+"=======receive: key = " + record.key() + ", value = " + record.value()+" offset==="+record.offset());
}*/
if (messageNo%10==0){
break;
}
messageNo++;
}
}else {
Thread.sleep(1000);
}
}
}catch (InterruptedException e){
e.printStackTrace();
}finally {
consumer.close();
}
}
public static void main(String args[]){
KafkaConsumerTest test1 = new KafkaConsumerTest("second");
Thread thread1 = new Thread(test1);
thread1.start();
}
}
运行
首先打包成jar包
然后放在Kafka集群上运行
运行命令如下👇
java -Djava.security.auth.login.config=/usr/hdp/current/kafka-broker/config/kafka_client_jaas.conf -Djava.security.krb5.conf=/etc/krb5.conf -jar KafKaProducer/out/artifacts/KafKaProducer_jar/KafKaProducer.jar
如果没有Kerberos认证可直接运行jar包
java -Djava.security.auth.login.config=/usr/hdp/current/kafka-broker/config/kafka_client_jaas.conf -Djava.security.krb5.conf=/etc/krb5.conf
这是环境配置文件,可以直接在IDEA中编写也可以在执行命令时带上,这是带有Kerberos认证时需要这两个配置文件
kafka_client_jaas.conf
这个文件在Kafka的安装目录中
krb5.conf
通常是在/etc
下
生产者运行结果,如图
java -Djava.security.auth.login.config=/usr/hdp/current/kafka-broker/config/kafka_client_jaas.conf -Djava.security.krb5.conf=/etc/krb5.conf -jar KafkaConsumer/out/artifacts/KafkaConsumer_jar/KafkaConsumer.jar
消费者运行结果
使用Kafka的控制台命令查看消息队列中的消息
打印结果是随机的,而我的消费者程序设置只打印10条,所以与生产数据对不上。
参考https://blog.csdn.net/qazwsxpcm/article/details/79186668