Title

kafka06-开发应用生产者和消费者

版本信息kafka 1.0.2

1生产者

生产者主要的对象有: KafkaProducer , ProducerRecord 。

其中 KafkaProducer 是用于发送消息的类, ProducerRecord 类用于封装Kafka的消息。

KafkaProducer 的创建需要指定的参数和含义:

参数 说明
bootstrap.servers 配置生产者如何与broker建立连接。该参数设置的是初始化参数。如果生
key.serializer 要发送信息的key数据的序列化类。设置的时候可以写类名,也可以使用该类的Class对象。
value.serializer 要发送消息的alue数据的序列化类。设置的时候可以写类名,也可以使用该类的Class对象。
acks 默认值:all。
acks=0:
生产者不等待broker对消息的确认,只要将消息放到缓冲区,就认为消息
已经发送完成。
该情形不能保证broker是否真的收到了消息,retries配置也不会生效。发
送的消息的返回的消息偏移量永远是-1。
acks=1
表示消息只需要写到主分区即可,然后就响应客户端,而不等待副本分区
的确认。
在该情形下,如果主分区收到消息确认之后就宕机了,而副本分区还没来
得及同步该消息,则该消息丢失。
acks=all
首领分区会等待所有的ISR副本分区确认记录。
该处理保证了只要有一个ISR副本分区存活,消息就不会丢失。
这是Kafka最强的可靠性保证,等效于 acks=-1
retries retries重试次数
当消息发送出现错误的时候,系统会重发消息。
跟客户端收到错误时重发一样。
如果设置了重试,还想保证消息的有序性,需要设置
MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION=1
否则在重试此失败消息的时候,其他的消息可能发送成功了

其他参数可以从 org.apache.kafka.clients.producer.ProducerConfig 中找到

消费者生产消息后,需要broker端的确认,可以同步确认,也可以异步确认。

同步确认效率低,异步确认效率高,但是需要设置回调对象。

package com.lew.demo;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.apache.kafka.common.header.Header;
import org.apache.kafka.common.header.internals.RecordHeader;
import org.apache.kafka.common.serialization.IntegerSerializer;
import org.apache.kafka.common.serialization.StringSerializer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @Author llewcg
 * @Description
 */
public class ProducerTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Map<String, Object> configs = new HashMap<>();
        // 设置连接Kafka的初始连接用到的服务器地址
        // 如果是集群,则可以通过此初始连接发现集群中的其他broker 一般设置2-3个即可
        configs.put("bootstrap.servers", "10.10.1.135:9092");
        // 设置key的序列化器
        configs.put("key.serializer", IntegerSerializer.class);
        // 设置value的序列化器
        configs.put("value.serializer", StringSerializer.class);

        KafkaProducer<Integer, String> producer = new KafkaProducer<>(configs);
        //设置自定义消息头
        List<Header> header = new ArrayList<>();
        header.add(new RecordHeader("biz.name", "producer".getBytes()));

        ProducerRecord<Integer, String> record = new ProducerRecord<Integer, String>(
                "gc_test1",
                0,
                11,
                "gcWell llewgc",
                header
        );

        //消息的同步确认等待
        Future<RecordMetadata> future = producer.send(record);
        RecordMetadata recordMetadata = future.get();
        System.out.println("主题:" + recordMetadata.topic());
        System.out.println("分区:" + recordMetadata.partition());
        System.out.println("偏移量:" + recordMetadata.hasOffset());

        //关闭生产者
        producer.close();
    }
}

消费者

[root@lew1 ~]# kafka-console-consumer.sh --bootstrap-server lew1:9092 --topic gc_test1 
gcWell llewgc

pom

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

2消费者

参数 说明
bootstrap.servers 与kafka建立连接的broker地址列表
key.deserializer key的反序列化器
value.deserializer value的反序列化器
group.id 消费组id,标识消费者所属消费组
auto.offset.reset 当kafka没有初始偏移量或偏移量不存在时
earliest:自动重置偏移量到最早的偏移量
lastest:到最新的偏移量
none:如果消费组原来偏移量不存在,向消费组抛出异常
nothing:向消费组抛出异常
package com.lew.demo.consumer;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.IntegerDeserializer;
import org.apache.kafka.common.serialization.StringDeserializer;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author llewcg
 * @Description
 */
public class ConsumerTest {
    public static void main(String[] args) {
        Map<String, Object> config = new HashMap<>();
        config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "lew1:9092");
        //key的反序列化器
        config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, IntegerDeserializer.class);
        //value的反序列化器
        config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        //消费组
        config.put(ConsumerConfig.GROUP_ID_CONFIG, "group_gc1");
        //找不到当前消费者的有效偏移量,则从最早的偏移量开始消费
        config.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");

        KafkaConsumer<Integer, String> consumer = new KafkaConsumer<>(config);
        consumer.subscribe(Arrays.asList("gc_test1"));
        while (true) {
            //批量从主题拉取数据
            //主题中没有可供拉取的消息时,没过3s拉取一次数据
            ConsumerRecords<Integer, String> consumerRecords = consumer.poll(3000);
            consumerRecords.forEach(x -> {
                System.out.println(x.topic() + "\t" +
                        x.partition() + "\t" +
                        x.offset() + "\t" +
                        x.key() + "\t" +
                        x.value());
            });
        }

    }
}
posted @ 2021-08-15 20:39  apeGcWell  阅读(39)  评论(0编辑  收藏  举报