kafka 学习笔记(二)

本文介绍了如何通过Kafka生产者发送消息,包括无回调、回调函数和指定分区的方式,同时讲解了消费者接收消息的技巧,以及自定义分区器、拦截器和offset存储的实现。深入探讨了如何在生产者和消费者中进行定制化操作。
摘要由CSDN通过智能技术生成

1. 生产者发送消息

Properties properties = new Properties();

// 设置地址, 这里所有的参数都在producerConfig这个类里
properties.put("bootstrap.servers", "localhost:9092");
properties.put("acks", "-1");    // 设置ack模式
properties.put("retries", "1");  // 重试次数
properties.put("batch.size", "16384");    // 批次大小
properties.put("linger.ms", "1");    // 等待时间
properties.put("buffer.memory", "33554432");    // 缓冲区大小
properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);
       
//  不带回调函数的,第一个参数topic,第二个是message
kafkaProducer.send(new ProducerRecord<String, String>("test", "hello"));

kafkaProducer.close();

生产者发送消息的集中姿势

KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);

// 1. 不带回调函数的
kafkaProducer.send(new ProducerRecord<String, String>("test", "hello"));

// 2. 增加回调函数
kafkaProducer.send(new ProducerRecord<String, String>("test", "hello"),
        new Callback() {
            @Override
            public void onCompletion(RecordMetadata metadata, Exception exception) {
                System.out.println(metadata.offset() + "----" + metadata.partition());
           }
        });

// 3. 指定数据的分区
// 第一个参数topic,第二个指定第几个分区,第三个指定key,第四个message
kafkaProducer.send(new ProducerRecord<String, String>("test",0,"atguigu", "love"),
     new Callback() {
            @Override
            public void onCompletion(RecordMetadata metadata, Exception exception) {
                System.out.println(metadata.offset() + "----" + metadata.partition());
            }
        });

2. 消费者接受消息

Properties properties = new Properties();

properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");  // 连接的地址
properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000"); //  自动提交延迟
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);  // 开启自动提交
properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

properties.put(ConsumerConfig.GROUP_ID_CONFIG, "atguigu");  // 设置消费者组

// 设置消费者的offset  earliest就是会获取最早的数据  latest 是从最新的数据开始获取
properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");

KafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties);

consumer.subscribe(Arrays.asList("test"));  // 订阅消息

while (true){
    // 获取数据
    ConsumerRecords<String, String> datas = consumer.poll(100);
    for (ConsumerRecord<String, String> data : datas) {
        System.out.println(data.key());
    }
}

当关闭自动提交之后,我们可以手动进行提交

KafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties);
consumer.subscribe(Arrays.asList("test"));

// 同步提交
consumer.commitSync(); 

// 异步提交
consumer.commitAsync(new OffsetCommitCallback() {
    @Override
    public void onComplete(Map<TopicPartition, OffsetAndMetadata> offsets, Exception exception) {
        System.out.println(offsets.keySet());
    }
});         

3. 自定义分区器

自定义分区器需要实现接口

public class Partitioner1 implements Partitioner {
    @Override
    public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
        // 返回分区编号
        return 1;
    }

    @Override
    public void close() {
       // 关闭
    }

    @Override
    public void configure(Map<String, ?> configs) {
        // 配置
    }
}

进行注册使用

// 需要在properties中进行全类名的注册
properties.put("partitioner.class", "com.data.spark.core.test.Partitioner1");

4. 自定义拦截器

public class MyTimeInterceptor implements ProducerInterceptor<String, String> {
    Integer success = 0;
    Integer error = 0;

    // 发送前对消息做的处理
    @Override
    public ProducerRecord<String, String> onSend(ProducerRecord<String, String> record) {
        // 获取数据
        String value = record.value();

        // 需要返回一个新的ProducerRecord对象
        return new ProducerRecord<>(record.topic(), record.partition(), record.key()
                ,System.currentTimeMillis()+", "+record.value());
    }

    // 成功发送到kafka的broker,或者发送过程失败会调用
    @Override
    public void onAcknowledgement(RecordMetadata metadata, Exception exception) {
        if(metadata != null){
            success += 1;
        }else {
            error -= 1;
        }
    }

    // 关闭过滤器,做清理工作
    @Override
    public void close() {
        System.out.println("closing...");
        System.out.println("success" + success);
        System.out.println("error" + error);
    }

    // 配置信息
    @Override
    public void configure(Map<String, ?> configs) {

    }
}

注册使用拦截器

// 在properties中进行全类名的注册,可以添加多个拦截器

ArrayList<String> interCeptors = new ArrayList<>();
interCeptors.add("com.data.spark.core.test.MyTimeInterceptor");
properties.put("interceptor.classes", interCeptors);

5. 自定义offset的存储

public class MyTest implements ConsumerRebalanceListener {
    @Override
    public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
        // 在Rebalance方法之前进行调用
    }

    @Override
    public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
        // 在Rebalance方法之后进行调用
    }
}

在消费端使用

kafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties);
consumer.subscribe(Arrays.asList("test"), new MyTest()); // 将自定义offset的存储对象传入

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值