kafka producer实例
1. 定义要发送的消息User POJO
package lenmom.kafkaproducer; public class User {
public String name;
public int age;
public String address; public User(String name,int age,String address){
this.name=name;
this.age=age;
this.address=address;
} @Override
public String toString() {
return "user:"+name +",age:"+age+",address:"+address;
}
}
2. 定义序列化User POJO序列化器
package lenmom.kafkaproducer; import org.apache.kafka.common.serialization.Serializer;
import org.codehaus.jackson.map.ObjectMapper; import java.util.Map; public class UserSerializer implements Serializer {
private ObjectMapper objectMapper; public void configure(Map map, boolean b) {
this.objectMapper = new ObjectMapper();
} public byte[] serialize(String topic, Object object) {
byte[] result = null;
try {
result = objectMapper.writeValueAsString(object).getBytes("utf-8");
} catch (Exception e) {
e.printStackTrace();
}
return result;
} public void close() { }
}
此序列化器使用了org.codehaus.jackson.jackson-mapper-asl.jar来进行序列化为jason
3. 定义partitioner
package lenmom.kafkaproducer; import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.PartitionInfo; import java.util.List;
import java.util.Map;
import java.util.Random; public class AgePartitioner implements Partitioner { private Random random; public int partition(String topic, Object keyObj, byte[] keyBytes, Object value,
byte[] valueBytes, Cluster cluster) {
System.out.println("key:"+keyObj.toString()+",value: "+value.toString()); Integer age = ((User)value).age;
List<PartitionInfo> partitions = cluster.availablePartitionsForTopic(topic);
int partitionCount = ((List) partitions).size();
int auditPartition = partitionCount - 1;
// 如果年龄大于20岁的,分发到kafka的最后一个分区,否则随机发送到前面几个分区中去
return age< 20 ? random.nextInt(partitionCount - 1) : auditPartition;
} public void close() { } public void configure(Map<String, ?> map) {
this.random = new Random();
}
}
4. 定义发送的消息统计拦截器
package lenmom.kafkaproducer; import org.apache.kafka.clients.producer.ProducerInterceptor;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata; import java.util.Map; public class CounterIntecepter implements ProducerInterceptor {
int count = 0;
int failedCount = 0; /*
* This method will be called before the message send to the broker
* */
public ProducerRecord onSend(ProducerRecord producerRecord) {
count += 1;
System.out.println("preparing to send value: " + producerRecord.value().toString());
return producerRecord;
} /*
* This method would be called when the message was handled by the borker after the broker call back.
*/
public void onAcknowledgement(RecordMetadata recordMetadata, Exception e) {
if (e != null) {
failedCount++;
}
} public void close() {
System.out.println("total: " + this.count + ",failed: " + this.failedCount);
} public void configure(Map<String, ?> map) { }
}
5. Producer主类
package lenmom.kafkaproducer; import org.apache.kafka.clients.producer.*; import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; public class ProducerDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Properties props = new Properties();
props.put("bootstrap.servers", "192.168.1.131:9092,192.168.1.193:9092,192.168.1.194:9092");
props.put("acks", "all"); //
props.put("retries", Integer.MAX_VALUE);
props.put("batch.size", 323840);
props.put("linger.ms", 100);
props.put("buffer.memory", 33554432);
props.put("max.block.ms", 3000);
props.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "lz4");
props.put(ProducerConfig.RETRIES_CONFIG, 3);
props.put("max.in.flight.requests.per.connection",1); testCustomSerializerProducer(props);
} private static void testCustomSerializerProducer(Properties props) throws ExecutionException, InterruptedException {
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "lenmom.kafkaproducer.UserSerializer");
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
//设置消息拦截器
List<String> interceptors= new ArrayList<String>();
interceptors.add("lenmom.kafkaproducer.CounterIntecepter");
props.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,interceptors); //设置自定义分区
props.put("partitioner.class", "lenmom.kafkaproducer.AgePartitioner"); final Producer<String, User> producer = new KafkaProducer<String, User>(props);
for (int i = 0; i < 100; i++) {
User user = new User("lenmom" + i, i, "address" + i);
ProducerRecord<String, User> record= new ProducerRecord<String, User>("lenmom", user);
producer.send(record, new Callback() {
public void onCompletion(RecordMetadata recordMetadata, Exception e) {
if (e != null) {
producer.close(0,TimeUnit.MILLISECONDS);
} else {
System.out.println("send success");
}
}
});
}
producer.close();
}
}
注意: KafkaProducer是线程安全的,也就是说可以在多个线程中共享一个KafkaProducer实例.
6. pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>lenmom</groupId>
<artifactId>kafkaproducer</artifactId>
<version>1.0-SNAPSHOT</version> <dependencies>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>0.10.1.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency> </dependencies> </project>
运行效果:
Producer执行效果
启动consumer:
$KAFKA_HOME/bin/kafka-console-consumer.sh --bootstrap-server 192.168.1.101: --topic lenmom --from-beginning
接收到的消息:
7. 配置参数说明
7.1 消息无丢失配置
7.1.1 Producer配置
7.1.1.1
#使得内存缓冲区被填满时producer 处于阻塞状态并停止接收新的消息而不是抛出异常;否则producer 生产速度过快会耗尽缓冲区
block.on.buffer.full =true
7.1.1.2
#设置acks 为all 很容易理解,即必须要等到所有fo llower 都响应了发送消息才能认为提交成功,这是pro ducer 端最强程度的持久化保证。
acks = all or 1
7.1.1.3
#重试次数设置为Integer.MAX_VALUE,设置成MAX_VALUE 纵然有些极端,但其实想表达的是producer 要开启无限重试。
#用户不必担心pro ducer 会重试那些肯定无法恢复的错误,当前producer 只会重试那些可恢复的异常
#情况,所以放心地设置一个比较大的值通常能很好地保证消息不丢失。
retries = Integer.MAX_VALUE
7.1.1.4
#设置该参数为1 主要是为工防止topic 同分区下的消息乱序问题。这个参数的实际效果其
#实限制了producer 在单个broker 连接上能够发送的未响应请求的数量。因此,如果设置成l ,
#则producer 在某个broker 发送响应之前将无法再给该broker 发送PRODUCE 请求
max.in.flight.requests.per.connection= 1
7.1.1.5
使用带有回调机制的send
不要使用KafkaPro ducer 中单参数的send 方法,因为该se nd 调用仅仅是把消息发出而不会理会消息发送的结果。如果消息发送失败,该方法不会得到任何通知,故可能造成数据的丢失。
实际环境中一定要使用带回调机制的send 版本,即KafkaProducer.send(record, callback) 。
7.1.1.6
Callback 逻辑中显式立即关闭producer
在Callback 的失败处理逻辑中显式调用KafkaProducer .close(O ) 。这样做的目的是为了处理消息的乱序问题。
若不使用close(O),默认情况下producer 会被允许将未完成的消息发送出去,这样就有可能造成消息乱序。
7.1.2 Broker消息无丢失设置
7.1.2.1
#broker关闭unclean leader 选举,即不允许非ISR 中的副本被选举为leader ,从而避免broker 端因日志水位截断而造成的消息丢失。
unclean.leader.election .enable= false
7.1.2.2
#broker 设置成3 主要是参考了Hadoop 及业界通用的三备份原则,其实这里想强调的是一定要使用多个副本来保存分区的消息。
replication.factor = 3
7.1.2.3
#broker 用于控制某条消息至少被写入到ISR 中的多少个副本才算成功,设置成大于1 是为了提升producer 端发送语义的持久性。
#记住只有在producer 端acks 被设置成all 或一l 时,这个参数才有意义。在实际使用时,不要使用默认值。
min.insync .replicas = 2
7.1.2.4
#btoker 若两者相等,那么只要有一个副本挂掉,分区就无法正常工作,虽然有很高的持久性但可用性被极大地降低了。推荐配置成replication.factor= min.insyn.replicas + l
replication.factor > min.insync.replicas
7.1.2.5
#broker 禁用自动提交
enable.auto.commit= false
7.2 压缩参数设置
producer使用压缩算法,可以提高kafka的吞吐量,目前支持的压缩算法有GZIP 、Snappy、LZ4和Facebook 公司于2016 年8 月底开源了新的压缩算法Zstandard。
配置方法为,在给producer的配置构造函数中加入对应的配置项,如:
props . put (” compressiont.typ”,” snappy");
//或者
props.put(ProducerConfig . COMPRESSION TYPE CONFIG ,”snappy”);
使用压缩算法,对集群的CPU有要求,建议的生产集群配置为:
linux
CPU 24 核
内存32GB 。
磁盘lTB 7200 转SAS 盘两块
带宽lGb/s
ulimit -n 1000000 。
Socket Buffer 至少64KB一一适用于跨机房网络传输。
kafka producer实例的更多相关文章
- kafka producer 源码总结
kafka producer可以总体上分为两个部分: producer调用send方法,将消息存放到内存中 sender线程轮询的从内存中将消息通过NIO发送到网络中 1 调用send方法 其实在调用 ...
- 【原创】Kafka producer原理 (Scala版同步producer)
本文分析的Kafka代码为kafka-0.8.2.1.另外,由于Kafka目前提供了两套Producer代码,一套是Scala版的旧版本:一套是Java版的新版本.虽然Kafka社区极力推荐大家使用J ...
- 【原创】kafka producer源代码分析
Kafka 0.8.2引入了一个用Java写的producer.下一个版本还会引入一个对等的Java版本的consumer.新的API旨在取代老的使用Scala编写的客户端API,但为了兼容性 ...
- 【转】Kafka producer原理 (Scala版同步producer)
转载自:http://www.cnblogs.com/huxi2b/p/4583249.html 供参考 本文分析的Kafka代码为kafka-0.8.2.1.另外,由于Kafka目前提供了两 ...
- 关于Kafka producer管理TCP连接的讨论
在Kafka中,TCP连接的管理交由底层的Selector类(org.apache.kafka.common.network)来维护.Selector类定义了很多数据结构,其中最核心的当属java.n ...
- 关于高并发下kafka producer send异步发送耗时问题的分析
最近开发网关服务的过程当中,需要用到kafka转发消息与保存日志,在进行压测的过程中由于是多线程并发操作kafka producer 进行异步send,发现send耗时有时会达到几十毫秒的阻塞,很大程 ...
- Kafka producer介绍
Kafka 0.9版本正式使用Java版本的producer替换了原Scala版本的producer.本文着重讨论新版本producer的设计原理以及基本的使用方法. 新版本Producer 首先明确 ...
- Kafka设计解析(十四)Kafka producer介绍
转载自 huxihx,原文链接 Kafka producer介绍 Kafka 0.9版本正式使用Java版本的producer替换了原Scala版本的producer.本文着重讨论新版本produce ...
- .net core kafka 入门实例 一篇看懂
kafka 相信都有听说过,不管有没有用过,在江湖上可以说是大名鼎鼎,就像天龙八部里的乔峰.国际惯例,先介绍生平事迹 简介 Kafka 是由 Apache软件基金会 开发的一个开源流处理平台, ...
随机推荐
- 无线模块 RXB12-315m TXB12-315M 应用
近期有个产品用到这对模块,因为没有什么技术支持,就直接上机调试.測试结果为带障碍发射距离60米. 下面是应用的几个知识点: 1:编程操作.事实上比較简单,调制信号315M是模块自带的,不须要调制和解调 ...
- 转JMeter ----数据库 not allowed to connect to this MySQL
测试的时候遇到报错: Cannot create PoolableConnectionFactory (null, message from server: "Host 'ceshiP ...
- ASP.NET AJAX入门系列(8):自定义异常处理
在UpdatePanel控件异步更新时,如果有错误发生,默认情况下会弹出一个Alert对话框显示出错误信息,这对用户来说是不友好的,本文看一下如何在服务端和客户端脚本中自定义异常处理,翻译自官方文档. ...
- Java生成PDF文档(表格、列表、添加图片等)
需要的两个包及下载地址: (1)iText.jar:http://download.csdn.net/source/296416 (2)iTextAsian.jar(用来进行中文的转换):http:/ ...
- 银行卡所属公司判断 参考自https://blog.csdn.net/well2049/article/details/79429130
在网上找到了一个银行卡的验证,通过阿里的支付宝接口进行校验,能够准确识别是否存在,归属行,卡号类型是储蓄卡(DC)还是信用卡(CC). 接口api:需要传入的2个参数,卡号cardNo和cardBin ...
- 《JavaScript设计模式与开发》笔记 6.高阶函数
1.函数作为参数传递 1.回调函数 2.Array.prototype.sort 2.函数作为返回值输出 1.判断数据的类型 3.高级函数的实现AOP 4.高阶函数的其他应用 1.currying 函 ...
- vi命令【方向键】变字母键的解决方法
vi命令[方向键]变字母键的解决方法 最近在SSH下玩Debian发现了一个有趣的现象,就是在一些个别版本的Debian镜像下,使用vi命令时会出现键盘输出出错的现象,使用方向键时会变成C,D等字 ...
- django获取表单数据
django获取单表数据的三种方式 v1 = models.Business.objects.all() # v1是QuerySet的列表 ,内部元素都是对象 v2 = models.Business ...
- HashSet的自定义实现
package com.cy.collection; import java.util.HashMap; /** * HashSet自定义实现 * 是使用hashMap实现的 * 可以看一下HashS ...
- 学习-工作:GTD
ylbtech-学习-工作:GTD GTD就是Getting Things Done的缩写,翻译过来就是“把事情做完”,是一个管理时间的方法.GTD的核心理念概括就是必须记录下来要做的事,然后整理安排 ...