5. 消费者消费数据

1. 开启进程

[node123]systemctl stop firewalld

[node123]zkServer.sh start

[node123]kafka-server-start.sh /opt/app/kafka-0.11.0.0/config/server.properties &

[node1]kafka-console-consumer.sh --zookeeper node1:2181 --topic demo

2. java导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>kafkacode</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-clients</artifactId>
            <version>0.11.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka_2.12</artifactId>
            <version>0.11.0.0</version>
        </dependency>
    </dependencies>
</project>

3. java代码

消费者消费带key值的数据
package new_consumer;

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;

/**
 * 连接我们的kafka集群进行消费  消费者 属于消费者组的
 *   创建消费者的时候需要指定消费者的一些相关配置  输入哪个消费者组、连接kafka集群的地址等等
 *
 *   自定义的消费者比kafka自带消费者的好处在于 我们可以消费key值
 *
 *   【注意】kafka中 生产者生产的数据是序列化存储的,因此消费者再消费数据的数据必须把数据反序列化回来
 */
public class ConsumerSelf {
    public static void main(String[] args) {
        Properties prop = new Properties();
        // 连接的kafka集群的地址
        prop.setProperty("bootstrap.servers","192.168.200.111:9092,192.168.200.112:9092,192.168.200.113:9092");
        // 设置一些消费者所属的消费者组
        prop.setProperty("group.id", "uek");
        // 是否自动确认offset  消费者再去消费某一个分区的时候,怎么知道消费者消息消费到哪个位置?
        prop.put("enable.auto.commit", "true");
        // 自动确认offset的时间间隔
        prop.put("auto.commit.interval.ms", "1000");
        // key的反序列化类
        prop.put("key.deserializer", "org.apache.kafka.common.serialization.IntegerDeserializer");
        // value的反序列化类
        prop.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

        // 泛型代表生产者生产的key value数据的类型
        KafkaConsumer<Integer, String> consumer = new KafkaConsumer<Integer, String>(prop);
        consumer.subscribe(Arrays.asList("demo"));

        while (true) {
            ConsumerRecords<Integer, String> records = consumer.poll(2000);
            for (ConsumerRecord<Integer, String> record: records) {
                System.out.println("当前消息的key值为" + record.key());
                System.out.println("当前消息的value值为" + record.value());
                System.out.println("当前消息的分区为" + record.partition());
            }
        }
    }
}
生产者生产带key值的数据
package new_partition_pro;

import org.apache.kafka.clients.producer.Callback;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import java.util.Properties;

// 新版本的生产者API  带有自定义分区和回调函数的生产者
public class NewProducerPartitionAndCallBack {
    public static void main(String[] args) {
        // 1、定义生产者连接Kafka集群的配置项   key-value格式的
        Properties prop = new Properties();
        prop.put("bootstrap.servers", "192.168.200.111:9092,192.168.200.112:9092,192.168.200.113:9092");
        // key序列化
        prop.put("key.serializer", "org.apache.kafka.common.serialization.IntegerSerializer");
        // value序列化
        prop.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        /**
         * 设置分区类的时候  要求类必须是public权限的(无法通过反射构建)
         * 第二个参数是全限定类名
         */
        prop.put("partitioner.class","new_partition_pro.CustomPartition");

        // 2. 创建一个生产者
        KafkaProducer<Integer, String> producer = new KafkaProducer<Integer, String>(prop);

        // 3、使用生产者向某个主题发送一个数据
        for (int i = 0; i < 100; i++) {
            ProducerRecord<Integer, String> record = new ProducerRecord<Integer, String>("demo", i, "hello" + i);

            final int finalI = i;

            /**
             * 方法就是kafka生产者消息发送完成之后,触发的一个回调函数
             * @param recordMetadata   包含当前这个消息在Topic主题中的分区和offset
             * @param e
             */
            producer.send(record, new Callback() {
                public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                    System.out.println("当前这个数据的分区为:"+recordMetadata.partition() + "---offset:" + recordMetadata.offset());
                    System.out.println("当前的key为:" + finalI);
                }
            });
        }

        /**
         * 4、代表将生产者生产的数据刷新到topic中
         */
        producer.flush();
    }
}
posted @ 2022-09-07 21:51  jsqup  阅读(44)  评论(0编辑  收藏  举报