通过https://www.cnblogs.com/tree1123/p/11243668.html 已经对consumer有了一定的了解。producer比consumer要简单一些。

一、旧版本producer

0.9.0.0版本以前,是由scala编写的旧版本producer。

入口类:kafka.producer.Producer

代码示例:

Properties properties = new Properties();
properties.put("metadata.broker.list", "kafka01:9092,kafka02:9092");
properties.put("serializer.class", "kafka.serializer.StringEncoder");
properties.put("request.requird.acks", "1");
ProducerConfig config = new ProducerConfig(properties);
Producer<String, String> producer = new Producer<String, String>(config);
KeyedMessage<String,String> msg = new KeyedMessage<String,String>("topic","hello");
Producer.send(msg);

旧版本是同步机制,等待响应。吞吐性很差。在0.9.0.0版本以后,正式下架了。

旧版本的方法:

send   发送
close 关闭
sync 异步发送 有丢失消息的可能性

二、新版本producer

旧版本producer由scala编写,0.9.0.0版本以后,新版本producer由java编写。

新版本主要入口类是:org.apache.kafka.clients.producer.KafkaProducer

常用方法:

send  实现消息发送主逻辑
close 关闭producer
metrics 获取producer的实时监控指标数据 比如发送消息的速率

Kafka producer要比consumer设计简单一些,主要就是向某个topic的某个分区发送一条消息。partitioner决定向哪个分区发送消息。用户指定key,默认的分区器会根据key的哈希值来选择分区,如果没有指定key就以轮询的方式选择分区。也可以自定义分区策略。

确定分区后,producer寻找到分区的leader,也就是该leader所在的broker,然后发送消息,leader会进行副本同步ISR。

producer会启两个线程,主线程封装ProducerRecord类,序列化后发给partitioner,然后发送到内存缓冲区。

另一个I/O线程,提取消息分batch统一发送给对应的broker。

示例代码:

Properties properties = new Properties();
properties.put("bootstrap.servers", "kafka01:9092,kafka02: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++) {
kafkaProducer.send(new ProducerRecord<String, String>("z_test_20190430", "testkafka0613"+i));
System.out.println("testkafka"+i);
}
kafkaProducer.close();

1、构造Properties对象,bootstrap.servers key.serializer value.serializer是必须指定的。

2、使用Properties构造KafkaProducer对象。

3、构造ProducerRecord 指定topic 分区 key value。

4、KafkaProducer的send方法发送。

5、关闭KafkaProducer。

Properties主要参数:

bootstrap.servers 和consumer一样,指定部分broker即可。而且broker端如果没有配ip地址,要写成主机名。

key.serializer value.serializer 序列化参数 一定要全类名 没有key也必须设置。

acks 三个值

​ 0: producer完全不管broker的处理结果 回调也就没有用了 并不能保证消息成功发送 但是这种吞吐量最高

​ all或者-1: leader broker会等消息写入 并且ISR都写入后 才会响应,这种只要ISR有副本存活就肯定不会丢失,但吞 吐量最低。

​ 1: 默认的值 leader broker自己写入后就响应,不会等待ISR其他的副本写入,只要leader broker存活就不会丢失,即保证了不丢失,也保证了吞吐量。

buffer.memory 缓冲区大小 字节 默认是33554432 就是发送消息的内存缓冲区大小 过小的话会影响吞吐量

compression.type 设置是否压缩消息 默认值是none 压缩后可以降低IO开销提高吞吐,但是会增大CPU开销。

​ 支持三种: GZIP Snappy LZ4 性能 LZ4 > Snappy > GZIP

retries 发送消息重试的次数 默认0 不重试 重试可能造成重复发送 可能造成乱序

​ retry.backoff.ms 设置重试间隔 默认100毫秒

batch.size 调优重要的参数 batch小 吞吐量也会小 batch大 内存压力会大 默认值是16384 16KB

linger.ms 发送延时 默认是0 0的话不用等batch满就发送 延时的话可以提高吞吐 看具体情况进行调整

max.request.size producer能够发送最大消息的大小 默认1048576字节 如果消息很大 需要修改它

request.timeout.ms 发送请求后broker在规定时间返回 默认30秒 超过就是超时了。

Send方法

fire and forget 就是上边的示例

Properties properties = new Properties();
properties.put("bootstrap.servers", "kafka01:9092,kafka02: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++) {
kafkaProducer.send(new ProducerRecord<String, String>("z_test_20190430", "testkafka0613"+i));
System.out.println("testkafka"+i);
}
kafkaProducer.close();

异步回调 不阻塞

Properties properties = new Properties();
properties.put("bootstrap.servers", "kafka01:9092,kafka02: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++) {
kafkaProducer.send(new ProducerRecord<String, String>("z_test_20190430", "testkafka0613"+i),new Callback(){
public void onCompletion(RecordMetadata metadata, Exception e) {
if(e != null) {
e.printStackTrace();
} else {
System.out.println("The offset of the record we just sent is: " + metadata.offset());
}
}
});
System.out.println("testkafka"+i);
}
kafkaProducer.close();

同步发送 无限等待返回

producer.send(record).get()

重试机制

如果需要自定义重试机制,就要在回调里对不同异常区别对待,常见的几种如下:

可重试异常

LeaderNotAvailableException :分区的Leader副本不可用,这可能是换届选举导致的瞬时的异常,重试几次就可以恢复

NotControllerException:Controller主要是用来选择分区副本和每一个分区leader的副本信息,主要负责统一管理分区信息等,也可能是选举所致。

NetWorkerException :瞬时网络故障异常所致。

不可重试异常

SerializationException:序列化失败异常

RecordToolLargeException:消息尺寸过大导致。

示例代码:

 producer.send(myRecord,
new Callback() {
public void onCompletion(RecordMetadata metadata, Exception e) {
if(e ==null){
//正常处理逻辑
System.out.println("The offset of the record we just sent is: " + metadata.offset()); }else{ if(e instanceof RetriableException) {
//处理可重试异常
......
} else {
//处理不可重试异常
......
}
}
}
});
分区机制

partitioner决定向哪个分区发送消息。用户指定key,默认的分区器会根据key的哈希值来选择分区,如果没有指定key就以轮询的方式选择分区。也可以自定义分区策略。

对于有key的消息,java版本的producer自带的partitioner会根据murmur2算法计算消息key的哈希值。然后对总分区数求模得到消息要被发送到的目标分区号。

自定义分区策略:

创建一个类,实现org.apache.kafka.clients.producer.Partitioner接口

主要分区逻辑在Partitioner.partition中实现:通过topic key value 一同确定分区

在构造KafkaProducer得Properties中设置partitioner.class 为自定义类 注意是全类名

序列化机制

常用的serializer

ByteArraySerializer.class

ByteBufferSerializer.class

BytesSerializer.class

DoubleSerializer.class

IntegerSerializer.class

LongSerializer.class

StringSerializer.class

但是其他一些复杂的就需要自定义序列化:

1、定义数据格式

2、创建自定义序列化类,实现org.apache.kafka.common.serialization.Serializer接口

3、在KafkaProducer的Properties中设置key.serializer value.serializer为自定义类

以上均为单线程的情况,但producer是线程安全的,单线程适合分区较少的情况,分区较多可以多线程但对内存损耗较大。

更多实时计算,Kafka等相关技术博文,欢迎关注实时流式计算

Kafka之Producer的更多相关文章

  1. 【转】 详解Kafka生产者Producer配置

    粘贴一下这个配置,与我自己的程序做对比,看看能不能完善我的异步带代码:   -----------------------------------------    详解Kafka生产者Produce ...

  2. Kafka的Producer和Consumer源码学习

    先解释下两个概念: high watermark (HW) 它表示已经被commited的最后一个message offset(所谓commited, 应该是ISR中所有replica都已写入),HW ...

  3. Kafka学习-Producer和Customer

    在上一篇kafka入门的基础之上,本篇主要介绍Kafka的生产者和消费者. Kafka 生产者 kafka Producer发布消息记录到Kakfa集群.生产者是线程安全的,可以在多个线程之间共享生产 ...

  4. Error when sending message to topic test with key: null, value: 2 bytes with error: (org.apache.kafka.clients.producer.internals.ErrorLoggingCallback)

    windows下使用kafka遇到这个问题: Error when sending message to topic test with key: null, value: 2 bytes with ...

  5. kafka 客户端 producer 配置参数

    属性 描述 类型 默认值 bootstrap.servers 用于建立与kafka集群的连接,这个list仅仅影响用于初始化的hosts,来发现全部的servers.格式:host1:port1,ho ...

  6. Kafka遇到30042ms has passed since batch creation plus linger time at org.apache.kafka.clients.producer.internals.FutureRecordMetadata.valueOrError(FutureRecordMetadata.java:94)

    问题描述: 运行生产者线程的时候显示如下错误信息: Expiring 1 record(s) for XXX-0: 30042 ms has passed since batch creation p ...

  7. 057 Java中kafka的Producer程序实现

    1.需要启动的服务 这里启动的端口是9092. bin/kafka-console-consumer.sh --topic beifeng --zookeeper linux-hadoop01.ibe ...

  8. Kafka: Producer (0.10.0.0)

    转自:http://www.cnblogs.com/f1194361820/p/6048429.html 通过前面的架构简述,知道了Producer是用来产生消息记录,并将消息以异步的方式发送给指定的 ...

  9. 【Kafka】Producer配置

    名称 描述 类型 默认值 bootstrap.servers kafka集群地址,ip+端口,以逗号隔开.不管这边配置的是什么服务器,客户端会使用所有的服务器.配置的列表只会影响初始发现所有主机.配置 ...

  10. Kafka生产者producer简要总结

    Kafka producer在设计上要比consumer简单,不涉及复杂的组管理操作,每个producer都是独立进行工作的,与其他producer实例之间没有关联.Producer的主要功能就是向某 ...

随机推荐

  1. GPS常识-A版(详)

    第一章 绪论 1.简述GPS系统的特点有哪些? GPS在测绘工程中应用的优点 P13 ●定位精度高 应用实践证明,相对静态定位1小时以上观测解,其平面位置:在300-1500m范围内,绝对误差小于1m ...

  2. 【CYH-02】NOIp考砸后虐题赛:成绩:题解

    这道题挺送水了吧... 两种做法. 其实空间都不需要那么大,我来提交界面一看一堆MLE的,于是还是良心的放开了时限. 这么简单,就不做解释了. 下面放出几种代码. 代码: 两个数组: #include ...

  3. Git对象

    上一节了解了 Git 的一个重要的概念:暂存区. 暂存区是一个介于工作区和版本库的中间状态,当执行commit时,实际上是将暂存区的内容提交大版本库中,而执行add则是将本次变更添加到暂存区. 上一节 ...

  4. 数据库---T-SQL语句(一)

    一.T-SQL语句 1.创建表:create table Name(Code varchar(50),) 主键:primary key 自增长:auto_increment 外键关系:referenc ...

  5. [mysql终极优化]之主从复制与读写分离详细设置教程

    读写分离与主从复制是提升mysql性能的重要及必要手段,大中型管理系统或网站必用之. 一.什么是读写分离与主从复制 先看图 如上图所示,当web server1/2/3要写入数据时,则向mysql d ...

  6. 嵌套&匿名&高阶函数

    嵌套&匿名&高阶函数 嵌套函数 函数可以嵌套定义并调用函数 name = "小明" def change(): name = "小明,你好" d ...

  7. django第一次(转自刘江大佬)

    下面的模型定义了一个“人”,它具有first_name和last_name字段: from django.db import models class Person(models.Model): fi ...

  8. spring读取xml配置文件(二)

    一.当spring解析完配置文件名的占位符后,就开始refresh容器 @Override public void refresh() throws BeansException, IllegalSt ...

  9. Linux中tree无法正常显示中文的解决方法

    tree命令以树状图列出目录的内容. 命令 tree -L n 的时候往往是无法正常显示中文的 先开始我以为是tree命令对中文是不支持的,后来百度了一下,网上有几个解决办法 安装新的tree可以解决 ...

  10. PageHelper分页实战(SSM整合)

    步骤一:引入SSM相关的jar包,包列表如下: 步骤二:创建或修改配置文件,配置文件清单如下: applicationContext.xml <?xml version="1.0&qu ...