【kafka】Kafka的JavaAPI操作(Streams API开发 生产者 开发者)

目录

创建maven工程并添加jar包

生产者代码

生产者代码

自定义分区条件

生产者生产数据到kafka集群,数据到分区的方式

消费者代码

自动提交offset

手动提交offset

消费完每个分区之后手动提交offset

指定分区数据进行消费

自动提交offset和手动提交offset的区别:

Consumer消费数据的流程:

Streams API开发

创建topic testt01 testt02:

开发StreamAPI

生产数据

消费数据


  • 创建maven工程并添加jar包

<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients -->
<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>1.0.0</version>
</dependency>   
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-streams</artifactId>
        <version>1.0.0</version>
</dependency>

</dependencies>

<build>
    <plugins>
        <!-- java编译插件 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.2</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>

 

  • 生产者代码

生产者代码

 //配置kafka集群环境(设置)
Properties props = new Properties();
//kafka服务器地址
props.put("bootstrap.servers", "node01:9092,node02:9092,node03:9092");
//消息确认机制
props.put("acks", "all");
//重试机制
props.put("retries", 0);
//批量发送的大小
props.put("batch.size", 16384);
//消息延迟
props.put("linger.ms", 1);
//批量的缓冲区大小
props.put("buffer.memory", 33554432);
//kafka   key 和value的序列化
props.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");
        props.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");

//自定义分区条件
//props.put("partitioner.class", "Producer.ProducerPartition");
        
//2、实例一个生产者对象
KafkaProducer<String, String> kafkaProducer = new KafkaProducer<String, String>(props);

for (int i = 0; i < 9; i++) {
//3、通过生产者对象将数据发送到kafka集群
       //1、没有指定分区编号,没有指定key,时采用轮询方式存户数据
       ProducerRecord producerRecord = new ProducerRecord("18BD12","bbbb___"+i);
       
       //2、没有指定分区编号,指定key时,数据分发策略为对key求取hash值,这个值与分区数量取余,于数就是分区编号。
       //ProducerRecord producerRecord = new ProducerRecord("18BD12","test","aaaa___"+i);
            
       //3、指定分区编号,所有数据输入到指定的分区内
       //ProducerRecord producerRecord = new ProducerRecord("18BD12",1,"test","aaaa___"+i);

       //4、定义分区策略
       //ProducerRecord producerRecord = new ProducerRecord("18BD12","test","aaaa___"+i);

       kafkaProducer.send(producerRecord);
}
//4、关闭成产者
kafkaProducer.close();

 

自定义分区条件

public class ProducerPartition implements Partitioner {
    @Override
    public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {

   /*
   编写自定义分区代码
    */

        //数据目标的分区
        return 0;
    }


    @Override
    public void close() {

    }

    @Override
    public void configure(Map<String, ?> configs) {

    }
}

 

 

生产者生产数据到kafka集群,数据到分区的方式

1.没有指定分区编号,没有指定key时采用轮询方式存储数据

2.没有指定分区编号,指定key时,数据分发策略为对key求取hash值,这个值与分区数量取余,于数就是分区编号。

3.指定分区编号,所有数据输入到指定的分区内

 

  • 消费者代码

自动提交offset

//1.添加配置文件
Properties props = new Properties();
//指定kafka服务器
props.put("bootstrap.servers", "node01:9092,node02:9092,node03:9092");
//消费组
props.put("group.id", "test");
//消费者自动提交offset值
 props.put("enable.auto.commit", "true");
//自动提交的周期
props.put("auto.commit.interval.ms",  "1000");
//kafka   key 和value的反序列化
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

//2.实例消费者对象
KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<String, String>(props);

//3.设置读取的topic
kafkaConsumer.subscribe(Arrays.asList("18BD12"));

//循环遍历
while (true){
    //4.拉取数据,并输出
    //获取到所有的数据返回记录的时间
    ConsumerRecords<String, String> consumerRecords = kafkaConsumer.poll(1000);
    //遍历所有数据,获得到一条
    for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
          //一条数据
          System.out.println("数据是  "+consumerRecord.value() + "偏移量是 "+consumerRecord.offset());
          }

}

 

 

手动提交offset

//1.配置文件
Properties props = new Properties();
//指定kafka服务器
props.put("bootstrap.servers", "node01:9092,node02:9092,node03:9092");
//消费组
rops.put("group.id", "test1");
//者自动提交offset值
props.put("enable.auto.commit", "false");
//自动提交的周期
//props.put("auto.commit.interval.ms",  "1000");
//kafka   key 和value的反序列化
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

//2.消费者
KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<String, String>(props);
        
//3.设置topic
kafkaConsumer.subscribe(Arrays.asList("18BD12"));

while (true){
    //4.拉取数据,并输出
    //获取到所有的数据返回记录的时间
    ConsumerRecords<String, String> consumerRecords = kafkaConsumer.poll(1000);
    //遍历所有数据获取一条
    for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
         System.out.println(consumerRecord.value()  +"     "+consumerRecord.offset());
    }

    //手动提交offset
    kafkaConsumer.commitSync();
 }

 

消费完每个分区之后手动提交offset

//1.配置文件
Properties props = new Properties();
//指定kafka服务器
props.put("bootstrap.servers", "node01:9092,node02:9092,node03:9092");
//消费组
rops.put("group.id", "test1");
//者自动提交offset值
props.put("enable.auto.commit", "false");
//自动提交的周期
//props.put("auto.commit.interval.ms",  "1000");
//kafka   key 和value的反序列化
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

//2.消费者
KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<String, String>(props);
        
//3.设置topic
kafkaConsumer.subscribe(Arrays.asList("18BD12"));

while (true){
      //4.拉取数据,并输出
      //获取到所有的数据返回记录的时间
      ConsumerRecords<String, String> consumerRecords = kafkaConsumer.poll(1000);
      //通过数据获取到多有的分区
      Set<TopicPartition> partitions = consumerRecords.partitions();
      //遍历所有分区,或得到一个分区
      for (TopicPartition partition : partitions) {
      //获取每个分区的数据,多条数据
      List<ConsumerRecord<String, String>> records = consumerRecords.records(partition);
       //遍历分区内的所有数据
            for (ConsumerRecord<String, String> record : records) {
                 System.out.println(record.value()+" "+record.partition());
           }
      //手动提交offset
      kafkaConsumer.commitSync();
}

 

指定分区数据进行消费

//1.配置文件
Properties props = new Properties();
//指定kafka服务器
props.put("bootstrap.servers", "node01:9092,node02:9092,node03:9092");
//消费组
rops.put("group.id", "test1");
//者自动提交offset值
props.put("enable.auto.commit", "false");
//自动提交的周期
//props.put("auto.commit.interval.ms",  "1000");
//kafka   key 和value的反序列化
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

//2.消费者
KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<String, String>(props);
        
//3.设置topic与分区
TopicPartition topicPartition0 = new TopicPartition("18BD12",0);
TopicPartition topicPartition2 = new TopicPartition("18BD12",1);
kafkaConsumer.assign(Arrays.asList(topicPartition0,topicPartition2));

//消费指定分区0和分区2中的数据,并且设置消费0分区的数据offerset值从0开始,消费2分区的数据offerset值从10开始
kafkaConsumer.seek(topicPartition0,0);
kafkaConsumer.seek(topicPartition1,10);

 while (true){
     //4.拉取数据,并输出
     //获取到所有的数据返回记录的时间
     ConsumerRecords<String, String> consumerRecords = kafkaConsumer.poll(1000);
     //通过数据获取到多有的分区  0   2
     Set<TopicPartition> partitions = consumerRecords.partitions();
     //遍历所有分区,或得到一个分区
     for (TopicPartition partition : partitions) {
           //获取每个分区的数据,多条数据
           List<ConsumerRecord<String, String>> records = consumerRecords.records(partition);
           //遍历分区内的所有数据,或得到一条
           for (ConsumerRecord<String, String> record : records) {
               System.out.println(record.value()+"      "+record.partition());
            }

       //手动提交offset
       kafkaConsumer.commitSync();
        }
}

 

自动提交offset和手动提交offset的区别:

1.自动提交会导致重复提交数据。

    2.手动消费,消费一点提交一点。

 

Consumer消费数据的流程:

1.Consumer连接指定的Topic partition所在leader broker。

2.采用pull方式从kafkalogs中获取消息。

3.高阶API封装了底层最原始的API,封装后的更简易(易使用)的API。隐藏Consumer与Broker细节。Offset保存在zookeeper。

4.低阶API有经过封装的最底层的API。API非常灵活,使用难度较大,比较繁琐。Offset保存在kafka的一个topic里  “__consumer_offsets”

 

  • Streams API开发

Kafka实时计算:实时生产 –->  实时传递 –->实时计算 –-> 实时存储 –-> 实时展现

需求:使用StreamAPI获取test01这个topic当中的数据,然后将数据全部转为大写,写入到test02这个topic当中去

 

创建topic testt01 testt02:

cd /export/servers/kafka_2.11-1.0.0/bin
./kafka-topics.sh --create  --partitions 3 --replication-factor 2 --topic test01 --zookeeper node01:2181,node02:2181,node03:2181

 

cd /export/servers/kafka_2.11-1.0.0/bin
./kafka-topics.sh --create  --partitions 3 --replication-factor 2 --topic test01 --zookeeper node01:2181,node02:2181,node03:2181

 

开发StreamAPI

Properties props = new Properties();
//设置程序的唯一标识
props.put(StreamsConfig.APPLICATION_ID_CONFIG, "wordcount-application12");
//设置kafka集群
props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "node01:9092,node02:9092,Node03:9092");
//设置序列化与反序列化
props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());
props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());

//实例一个计算逻辑
StreamsBuilder streamsBuilder = new StreamsBuilder();
//设置计算逻辑
// stream 在哪里读取数据  ->
// to 将数据写入哪里
streamsBuilder.stream("test01").mapValues(line -> line.toString().toUpperCase()).to("test02");

//构建Topology对象(拓扑,流程)
final Topology topology = streamsBuilder.build();

//实例 kafka流
KafkaStreams streams = new KafkaStreams(topology, props);

//启动流计算
streams.start();

 

生产数据

node01执行以下命令,向test01这个topic当中生产数据

cd /export/servers/kafka_2.11-1.0.0/bin
./kafka-console-producer.sh --broker-list node01:9092,node02:9092,node03:9092 --topic test01

 

消费数据

node02执行以下命令消费test02这个topic当中的数据

cd /export/servers/kafka_2.11-1.0.0/bin
./kafka-console-consumer.sh --from-beginning  --topic test02 --zookeeper node01:2181,node02:2181,node03:2181

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值