Kafka四(生产者API)

首先需要引入Kafka客户端依赖

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

步骤

  1. 定义生产者属性
  2. 创建生产者对象
  3. 发送消息

生产者发送消息有三种方式

  1. 发送并忘记
    把消息发送给服务器,但是不关心它是否正常到达,大多数情况下,消息会正常到达,而且生产者也会尝试重发,不过也有可能造成数据丢失
  2. 同步发送
    通过send()方法发送消息,send接口会返回一个Future对象,调用get方法进行等待,get方法完成即发送成功
  3. 异步发送
    通过send()方法发送消息,同事指定一个回调函数,服务器再返回响应时调用该函数

1: 同步发送

import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;

public class Producer {

  public static void main(String args[]) throws ExecutionException, InterruptedException {
    Properties properties = new Properties();
    properties.put("bootstrap.servers", "localhost:9092");
    properties.put("acks", "all");
    properties.put("retries", 0);
    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<String, String>(properties);
    for (int i = 1; i <= 600; i++) {
      // 参数 1:主题  2:key 3:value
      Future<RecordMetadata> future =
          kafkaProducer.send(new ProducerRecord<String, String>("kafka-action", "key","topic"+i));
      // 可通过结果获取偏移量,分区等信息    
      RecordMetadata metadata = future.get();
      System.out.println(metadata);
    }
    kafkaProducer.close();
  }
}

2 异步发送

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

public class Producer {

  public static void main(String args[]){
    Properties properties = new Properties();
    properties.put("bootstrap.servers", "localhost:9092");
    properties.put("acks", "all");
    properties.put("retries", 0);
    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<String, String>(properties);
    for (int i = 1; i <= 600; i++) {

      Callback callback = (recordMetadata, e)-> {
        if(e != null){
          e.printStackTrace();
        }
      };

      // 参数 1:主题  2:key 3:value
      kafkaProducer.send(new ProducerRecord<String, String>("kafka-action", "key","topic"+i),
          callback);
    }
    kafkaProducer.close();
  }
}

Kafka 生产者的Java API很简单,重要的是里面各种参数的意义,接下来认识一下。

  1. bootstrap.servers
    指定broker的地址清单,格式为host:port,建议提供两个以上broker的信息,for example
    “localhost:9092,localhost:9093”

  2. acks
    指定必须要有多少分区副本收到消息生产者才认为消息写入是成功的,这个参数对保证消息不丢失有非常重要的影响,主要有 如下选项
    acks=0, 生产者在消息发送后不会等待服务器的响应,如果当中因为网络等出现了问题,导致服务器没有收到消息,那么就会造成数据丢失,不过,因为生产者不用等待服务器的响应,所以生产者可以支持更高的吞吐量
    acks=1, 只要所有分区的leader副本节点收到消息,生产者就会收到一个服务器的成功响应,如果消息无法到达leader节点(比如leader节点意外崩溃,而新的leader节点还没有选取出来),生产者会收到一个错误响应,一般情况下,生产者会重发消息,不过如果一个没有收到消息的节点成为新首领,消息还是会丢失,这个时候吞吐量取决于使用的是同步发送还是异步发送。
    acks=all, 只有当所有分区副本都收到消息时,生产者才会收到一个来自服务器的成功响应,这种模式时最安全的,它可以保证不止一个服务器收到消息,就算有服务器发生崩溃,整个集群还可以继续运行,但是由于要等待所有服务器收到消息后才成功,因此延迟会比acks=1时高。

  3. buffer.memory
    此参数用来设置生产者内存缓冲区大小,生产者用它缓冲要发送到服务器的消息,如果应用程序发送消息的速度超过发送到服务器的速度,会导致空间不足,这个时候,send方法要么阻塞,要么抛出异常,取决于max.block.ms参数。

  4. compression.type
    默认情况下,消息不会被压缩。该参数可以设置为snappy、gzip、lz4,它指定了消息使用什么方式压缩。

  5. retries
    retries参数指定生产者可以重发消息的次数,如果超过这个次数,生产者会放弃重试并返回错误。生产者发送给服务器的消息有可能因为网络等各种原因导致发送失败,在这种情况下,可以进行重发,默认情况下,生产者会在每次重试之前等待100ms,不过可以通过retry.backoff.ms来改变这个时间间隔。

  6. batch.size
    当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一批次里,统一发送。这个参数指定了一个批次可以使用的内存大小,按照字节数计算(不是消息个数)。当批次被填满,批次里所有消息就会发送出去,不过生产者并不保证一定都会等到批量被填满才被发送,半满甚至一个消息的批次也有可能被发送。所以就算把批次大小设置得很大,也不会造成延迟,内部会动态计算,只是会占用更加多得内存,但是如果设置得太小,生产者发送消息得次数则会增多,会增加一些额外网络开销。

  7. linger.ms
    该参数指定生产者在发送批次之前等待更多消息进入此批次的时间,生产者会在批次填满或者linger.ms时间到达的时候发送出去。默认情况下,只要有可用的线程,生产者就会把消息发送出去,就算批次只有一个消息。把 linger.ms设置成比0大的数,
    让生产者在发送批次之前等待一会儿,使更多的消息加入到这个批次。虽然这样会增加延迟,但会提升吞吐量(因为一次性发送更多的消息,每个消息的开销就变小了)。

  8. client.id
    客户端id

  9. max.in.flight.requests.per.connection
    生产者在收到服务器响应之前可以发送多少消息。值越高,就会占用更多的内存,不过也会提升吞吐量,设置成1的话可以保证消息时按照发送的顺序写入服务器的,即使发生了重试。

  10. timeout.ms、 request.timeout.ms 、metadata.fetch.timeout.ms
    request.timeout.ms指定生产者发送数据等待服务器响应的时间
    metadata.fetch.timeout.ms指定生产者获取元数据(比如目标分区leader节点是谁)时等待服务器响应的时间
    timeout.ms 指定broker等待同步副本返回消息确认的时间,与acks的配置像批量,如果在指定时间没有收到副本的同步确认,那么broker就会返回一个错误

  11. max.block.ms
    指定调用send方法或者partitionsFor方法获取元数据时生产者的阻塞时间。当生产者的发送缓冲区满或者没有可用的元数据时,这些方法就会阻塞,在达到max.block.ms配置的时间时就会抛出异常。

  12. max.request.size
    生产者发送的请求大小,可以指定能发送的单个消息的最大值,也可以指定单个请求里所有消息总的大小,例如这个值为1MB,那么可以发送的单个最大消息就是1MB,或者生产者可以在单个请求里发送一个批次,该批次包含了1000个消息,每个消息的大小为1KB,所有消息综合不能超过1MB。

  13. message.max.bytes
    可接收的消息最大值。

  14. receive.buffer.bytes 和 send.buffer.bytes
    指定TCP socker接收和发送数据包的缓冲区大小,如果设置成-1,那么使用操作系统的默认值,如果生产者、消费者与broker处于不同的数据中心,那么可以适当增大,因为跨数据中心的网络一般都有比较高得延迟和比较低的带宽。

  15. key.serializer
    broker希望接收到消息的键是字节数据。生产者接口允许使用参数化类型,因此可以把Java对象作为键发送给broker,这样代码具有非常良好的可读性,不过生产者需要知道如何把这些Java对象转成字节数组,key.serializer需指定一个实现了一个实现了org.apache.kafka.common.serialization.Serializer接口的类,Kafka clients默认提供了IntegerSerializer、StringSerializer等基本序列化器的实现,如果只是用常见的Java对象类型,那么就没有必要实现自己的序列化器,key.serializer是必须设置的。

  16. value.serializer
    和key.serializer一样,value也可以被指定的类序列化。

Kafka保证同一个分区内的消息是有序的,如果生产者按照一定的顺序发送消息到一个分区,那么broker就会按照这个顺序写入分区,消费者也会按照同样的顺序读取出来, 如下图
在这里插入图片描述

图1-1

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值