Kafka学习笔记(四)Kafka API

4. Kafka API

4.1 Producer API

4.1.1 消息发送流程

Kafka 的 Producer 发送消息采用的是异步发送的方式。在消息发送的过程中,涉及到了 两个线程——main 线程和 Sender 线程,以及一个线程共享变量——RecordAccumulator。 main 线程将消息发送给 RecordAccumulator,Sender 线程不断从 RecordAccumulator 中拉取 消息发送到 Kafka broker。

相关参数:

batch.size:只有数据积累到 batch.size 之后,sender 才会发送数据。

linger.ms:如果数据迟迟未达到 batch.size,sender 等待 linger.time 之后就会发送数据。

4.1.2 异步发送 API

导入依赖:

<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>0.11.0.0</version>
</dependency>
  1. 不带回调函数的 API:
import org.apache.kafka.clients.producer.*;
import java.util.Properties;
import java.util.concurrent.ExecutionException;

public class CustomProducer1 {
public static void main(String[] args) throws ExecutionException, InterruptedException{
    Properties props = new Properties();
    
   /**	也可以用ProducerConfig类进行参数配置,用这种方法的较多
     *     //kafka集群
     *     props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop102:9092");
     *     //ack应答级别
     *     props.put(ProducerConfig.ACKS_CONFIG, "all");
     *
     *     //重试次数
     *     props.put(ProducerConfig.RETRIES_CONFIG, 1);
     *     //批次大小,16k
     *     props.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
     *     //等待时间,1ms
     *     props.put(ProducerConfig.LINGER_MS_CONFIG, 1);
     *     //RecordAccumulator 缓冲区大小,32M
     *     props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 33554432);
     */

    //kafka集群
    props.put("bootstrap.servers", "hadoop102:9092");
    //ack应答级别
    props.put("ack", "all");

    //重试次数
    props.put("retries", 1);
    //批次大小,16k
    props.put("batch.size", 16384);
    //等待时间,1ms
    props.put("linger.ms", 1);
    //RecordAccumulator 缓冲区大小,32M
    props.put("buffer.memory", 33554432);
    //key,value的序列化类
    props.put("key.serializer",
            "org.apache.kafka.common.serialization.StringSerializer");
    props.put("value.serializer",
            "org.apache.kafka.common.serialization.StringSerializer");
    //创建生产者对象
    Producer<String, String> producer = new KafkaProducer<>(props);
    for (int i = 0; i < 10; i++) {
        producer.send(new ProducerRecord<>("first",
                "测试数据--" + i));
    }
    //关闭资源
    producer.close();
    }
}

在kafka集群上启动一个代码中对应的消费者:
在这里插入图片描述

  1. 带回调函数的 API:
package com.tianyi.kafka.producer;

import org.apache.kafka.clients.producer.*;
import java.util.Properties;
import java.util.concurrent.ExecutionException;

/**
* CustomProducer2
*   带回调函数
* @author hutianyi
* @date 2022/6/6
**/
public class CustomProducer2 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
    Properties props = new Properties();
    props.put("bootstrap.servers", "hadoop102:9092");//kafka 集群,broker-list
    props.put("acks", "all");
    props.put("retries", 1);//重试次数
    props.put("batch.size", 16384);//批次大小
    props.put("linger.ms", 1);//等待时间
    props.put("buffer.memory", 33554432);//RecordAccumulator 缓冲区大小
    props.put("key.serializer",
            "org.apache.kafka.common.serialization.StringSerializer");
    props.put("value.serializer",
            "org.apache.kafka.common.serialization.StringSerializer");
    Producer<String, String> producer = new
            KafkaProducer<>(props);
    for (int i = 0; i < 10; i++) {
        producer.send(new ProducerRecord<>("first",
                "测试数据---" + i), new Callback() {
            //回调函数,该方法会在 Producer 收到 ack 时调用,为异步调用
            @Override
            public void onCompletion(RecordMetadata metadata,
                                     Exception exception) {
                if (exception == null) {
                    System.out.println(metadata.partition() + "---" + metadata.offset());
                } else {
                    exception.printStackTrace();
                }
            }
        });
    }
    producer.close();
    }
}

控制台输出:

4.2 Consumer API

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 java.util.Arrays;
import java.util.Properties;

public class CustomConsumer1 {
    public static void main(String[] args) {

        //创建消费者配置信息
        Properties props = new Properties();
        //连接的集群
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop102:9092");
        //消费者组
        props.put(ConsumerConfig.GROUP_ID_CONFIG, "bigdata");
        //开启自动提交
        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");
        //自动提交的延时
        props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
        //key,value的反序列化
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
                "org.apache.kafka.common.serialization.StringDeserializer");
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
                "org.apache.kafka.common.serialization.StringDeserializer");
        // //重置消费者的offset
		// props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
        //创建消费者
        KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
        //订阅主题
        consumer.subscribe(Arrays.asList("first"));
        //获取数据
        while (true) {
            ConsumerRecords<String, String> records = consumer.poll(100);
            //解析并打印
            for (ConsumerRecord<String, String> record : records){
                System.out.printf("offset = %d, key = %s, value = %s%n",
                        record.offset(), record.key(), record.value());
            }
        }
    }
}

用4.1作为生产者去消费数据:加一个key的参数

 producer.send(new ProducerRecord<>("first", "tianyi", "测试数据--" + i));

**重置消费者的offset后,可以将历史数据都消费到,但是必须得修改组名。**即要消费到所有的历史数据,需要满足两个条件:

1)props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); //将offset设置为earliest2)props.put(ConsumerConfig.GROUP_ID_CONFIG, "xxxx"); //修改这个组名

4.3 手动异步提交offset

import org.apache.kafka.clients.consumer.*;
import org.apache.kafka.common.TopicPartition;
import java.util.Arrays;
import java.util.Map;
import java.util.Properties;

public class CustomConsumer3 {
    public static void main(String[] args) {
        Properties props = new Properties();
        //Kafka 集群
        props.put("bootstrap.servers", "hadoop102:9092");
        //消费者组,只要 group.id 相同,就属于同一个消费者组
        props.put("group.id", "test");
        //关闭自动提交 offset
        props.put("enable.auto.commit", "false");
        props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
        consumer.subscribe(Arrays.asList("first"));//消费者订阅主题
        while (true) {
            ConsumerRecords<String, String> records = consumer.poll(100);//消费者拉取数据
            for (ConsumerRecord<String, String> record : records) {
                System.out.printf("offset = %d, key = %s, value = %s%n",
                        record.offset(), record.key(), record.value());
            }
            //异步提交
            consumer.commitAsync(new OffsetCommitCallback() {
                @Override
                public void onComplete(Map<TopicPartition,
                        OffsetAndMetadata> offsets, Exception exception) {
                    if (exception != null) {
                        System.err.println("Commit failed for" + offsets);
                    }
                }
            });
        }
    }
}

总结

本文介绍了kafka0.11版本生产者和消费者使用的基本API,新版本提供了更加丰富的API,但是使用方式大致是类似的,可以对照官网使用新版本的kafka版本和API,另外,对于kafka集群的参数一般都是使用ProducerConfig / ConsumerConfig去设定的,本文中的部分示例用的是参数名的形式,两种都是可以的,推荐使用配置类去设置参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半岛铁子_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值