kafka-java客户端操作

1、首先创建一个topic,三个分区,三个副本

[root@haha-01 kafka_2.11-1.1.0]# bin/kafka-topics.sh --create --zookeeper 192.168.6.133:2181 --replication-factor 3 --partitions 3 --topic haha

2、添加maven依赖

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

3、消息发送

    构建一个消费发送的程序一般有下面几步:

  • 创建一个简单的首先配置Properties 生产端属性。
  • 根据属性实例化一个KafkaProducer对象
  • 实例化一个ProducerRecord对象指定topic 、key、value
  • 调用KafkaProducer对象的send方法
  • 关闭连接,释放资源

 

3.1配置Kafka连接信息

   /**
     * 配置Kafka连接信息.
     * bootstrap.servers、key.serializer、value.serializer是
     * 必须要配置的,其他可以按需添加配置。
     * 配置对应的类:org.apache.kafka.clients.producer.ProducerConfig
     * 可以查看ProducerConfig的属性,进行其他的一些配置
     * @return
     */
    public Properties configure() {
        Properties props = new Properties();
        //用于初始化时建立链接到kafka集群,以host:port形式,多个以逗号分隔host1:port1,host2:port2。
        props.put("bootstrap.servers", "192.168.6.133:9092,192.168.6.133:9093,192.168.6.133:9094");
        props.put("acks", "1"); // 设置应答模式, 1表示有一个Kafka代理节点返回结果
        //发送失败时,指定生产者可以重发消息的次数。
        props.put("retries", 0); // 重试次数
        props.put("batch.size", 16384); // 批量提交大小
        //指定了生产者在发送批次前等待更多消息加入批次的时间。
        props.put("linger.ms", 1);
        //设置生产者内存缓冲区的大小,生产者用它缓冲要发送到服务器的消息。
        props.put("buffer.memory", 33554432); // 缓冲大小
        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); // 序列化主键
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");// 序列化值
        return props;
    }

相关配置介绍

注意:bootstrap.servers、key.serializer、value.serializer是必须要配置的,其他可以按需添加配置。

生产者有很多属性可以设置,大部分都有合理的默认值,无需调整。有些参数可能对内存使用,性能和可靠性方面有较大影响。生产者所有的配置都在org.apache.kafka.clients.producer.ProducerConfig这个类里。比如acks,

3a4934d1d264401a07be70883bdda851381.jpg

ACKS_CONFIG 配置的属性,ACKS_DOC 为属性的文档说明。下面介绍一下主要的几个配置。

acks:
指定了必须要有多少个分区副本收到消息,生产者才会认为写入消息是成功的,这个参数对消息丢失的可能性有重大影响。
acks=0:生产者在写入消息之前不会等待任何来自服务器的响应,容易丢消息,但是吞吐量高。
acks=1:只要集群的首领节点收到消息,生产者会收到来自服务器的成功响应。如果消息无法到达首领节点(比如首领节点崩溃,新首领没有选举出来),生产者会收到一个错误响应,为了避免数据丢失,生产者会重发消息。不过,如果一个没有收到消息的节点成为新首领,消息还是会丢失。默认使用这个配置。
acks=all:只有当所有参与复制的节点都收到消息,生产者才会收到一个来自服务器的成功响应。延迟高。

buffer.memory:
设置生产者内存缓冲区的大小,生产者用它缓冲要发送到服务器的消息。如果数据产生速度大于向broker发送的速度,导致生产者空间不足,producer会阻塞或者抛出异常。缺省33554432 (32M)
retries:
发送失败时,指定生产者可以重发消息的次数。默认情况下,生产者在每次重试之间等待100ms,可以通过参数retry.backoff.ms参数来改变这个时间间隔。缺省0
batch.size:
当多个消息被发送同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。当批次内存被填满后,批次里的所有消息会被发送出去。但是生产者不一定都会等到批次被填满才发送,半满甚至只包含一个消息的批次也有可能被发送。缺省16384(16k)
linger.ms:
指定了生产者在发送批次前等待更多消息加入批次的时间。它和batch.size以先到者为先。也就是说,一旦我们获得消息的数量够batch.size的数量了,他将会立即发送而不顾这项设置,然而如果我们获得消息字节数比batch.size设置要小的多,我们需要“linger”特定的时间以获取更多的消息。这个设置默认为0,即没有延迟。设定linger.ms=5,例如,将会减少请求数目,但是同时会增加5ms的延迟,但也会提升消息的吞吐量。

3.2发送消息

发送消息有同步发送和异步回调发送,同步会阻塞,降低吞吐量,一般都会采用异步回调的方式。

同步:

    @Test
    public void testSys(){
        //Kafka连接信息对象
        Properties configure = configure();
        //构建一个生产者
        KafkaProducer<String, String> producer = new KafkaProducer<String, String>(configure);
        try {
            ProducerRecord<String, String> record;
            try {
                record = new ProducerRecord<String, String>("haha",
                        "12134", "sys hello world");
                Future<RecordMetadata> future = producer.send(record);
                RecordMetadata recordMetadata = future.get();//会阻塞直到kafka返回信息
                log.debug("RecordMetadata----partition:{},offset:{}",recordMetadata.partition(),recordMetadata.offset());

            } catch (Exception e) {
                e.printStackTrace();
            }
        } finally {
            producer.close();
        }
    }

ba33c451c7167cad845981b8b751c623d4a.jpg

 

异步回调:

   /**
     * 异步回调发送
     */
    @Test
    public void testAsy() throws InterruptedException {
        Properties configure = configure();
        KafkaProducer<String, String> producer = new KafkaProducer<String, String>(configure);
        try {
            ProducerRecord<String, String> record;
            try {
                record = new ProducerRecord<String, String>("haha",
                        "12134", "asy hello world");
               producer.send(record,new Callback() {
                   public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                       if (e != null) {
                           log.error("Send error, msg is " + e.getMessage());
                       } else {
                           log.debug("RecordMetadata----partition:{},offset:{}",recordMetadata.partition(),recordMetadata.offset());
                       }
                   }
               });

            } catch (Exception e) {
                e.printStackTrace();
            }
        } finally {
            producer.close();
        }

        TimeUnit.SECONDS.sleep(5);
    }

e513119a4d7f833228e4bb51843722a4f53.jpg

 

4、消费消息

  • 首先初始化连接的配置信息
  • 构建KafkaConsumer对象
  • 调用subscribe方法订阅话题
  • 调用poll方法从kafka服务里拉取消息
  • 循环处理

关于消费者的属性配置在org.apache.kafka.clients.consumer.ConsumerConfig这个类里面,包括所有消费端的配置,每条属性配置下面都有介绍说明。

@Slf4j
public class HelloKafkaConsumer {

    /** 初始化Kafka集群信息. */
    private Properties configure() {
        Properties props = new Properties();
        //用于初始化时建立链接到kafka集群,以host:port形式,多个以逗号分隔host1:port1,host2:port2。
        props.put("bootstrap.servers", "192.168.6.133:9092,192.168.6.133:9093,192.168.6.133:9094");
        props.put("group.id", "haha01");// 指定消费者组
        props.put("enable.auto.commit", "true");// 开启自动提交
        props.put("auto.commit.interval.ms", "1000");// 自动提交的时间间隔
        // 反序列化消息主键
        props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        // 反序列化消费记录
        props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        return props;
    }

    @Test
    public void test(){
        Properties properties = configure();
        KafkaConsumer<String,String> consumer
                = new KafkaConsumer<String, String>(properties);
        try {
            consumer.subscribe(Collections.singletonList("haha"));
            while(true){
                ConsumerRecords<String, String> records
                        = consumer.poll(500);
                for(ConsumerRecord<String, String> record:records){
                    log.info("topic:{},分区:{},偏移量:{},key:{},value:{}",record.topic(),
                            record.partition(),record.offset(),record.key(),record.value());
                    //do bussiness
                }
            }
        } finally {
            consumer.close();

        }
    }

}

 

消费者相关配置  
消费者有很多属性可以设置,大部分都有合理的默认值,无需调整。有些参数可能对内存使用,性能和可靠性方面有较大影响。可以参考org.apache.kafka.clients.consumer包下ConsumerConfig类。
fetch.min.bytes    
每次fetch请求时,server应该返回的最小字节数。如果没有足够的数据返回,请求会等待,直到足够的数据才会返回。缺省为1个字节。多消费者下,可以设大这个值,以降低broker的工作负载
fetch.wait.max.ms    
如果没有足够的数据能够满足fetch.min.bytes,则此项配置是指在应答fetch请求之前,server会阻塞的最大时间。缺省为500个毫秒。和上面的fetch.min.bytes结合起来,要么满足数据的大小,要么满足时间,就看哪个条件先满足。
max.partition.fetch.bytes
指定了服务器从每个分区里返回给消费者的最大字节数,默认1MB。假设一个主题有20个分区和5个消费者,那么每个消费者至少要有4MB的可用内存来接收记录,而且一旦有消费者崩溃,这个内存还需更大。注意,这个参数要比服务器的message.max.bytes更大,否则消费者可能无法读取消息。
session.timeout.ms
如果consumer在这段时间内没有发送心跳信息,则它会被认为挂掉了。默认3秒。
auto.offset.reset    
消费者在读取一个没有偏移量的分区或者偏移量无效的情况下,如何处理。默认值是latest,从最新的记录开始读取,另一个值是earliest,表示消费者从起始位置读取分区的记录。

注意:默认值是latest,意思是说,在偏移量无效的情况下,消费者将从最新的记录开始读取数据(在消费者启动之后生成的记录),可以先启动生产者,再启动消费者,观察到这种情况。观察代码,在模块kafka-no-spring下包hellokafka中。
enable .auto.commit    
默认值true,表明消费者是否自动提交偏移。为了尽量避免重复数据和数据丢失,可以改为false,自行控制何时提交。
partition.assignment.strategy
分区分配给消费者的策略。系统提供两种策略。默认为Range。允许自定义策略。
Range
把主题的连续分区分配给消费者。例如,有主题T1和T2,各有3个分区,消费者C1和C2,则可能的分配形式为:
C1: T1(0,1),T2(0,,1)
C2: T1(2),T2(2)
RoundRobin
把主题的分区循环分配给消费者。例如,有主题T1和T2,各有3个分区,消费者C1和C2,则可能的分配形式为:
C1: T1(0,2),T2(1)
C2: T1(1),T2(0,2)
自定义策略
extends 类AbstractPartitionAssignor,然后在消费者端增加参数:
properties.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG, 类.class.getName());即可。
client.id    
当向server发出请求时,这个字符串会发送给server。目的是能够追踪请求源头,以此来允许ip/port许可列表之外的一些应用可以发送信息。这项应用可以设置任意字符串,因为没有任何功能性的目的,除了记录和跟踪。
max.poll.records
控制每次poll方法返回的的记录数量。
receive.buffer.bytes和send.buffer.bytes
指定TCP socket接受和发送数据包的缓存区大小。如果它们被设置为-1,则使用操作系统的默认值。如果生产者或消费者处在不同的数据中心,那么可以适当增大这些值,因为跨数据中心的网络一般都有比较高的延迟和比较低的带宽。

转载于:https://my.oschina.net/suzheworld/blog/3003847

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值