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实例的更多相关文章

  1. kafka producer 源码总结

    kafka producer可以总体上分为两个部分: producer调用send方法,将消息存放到内存中 sender线程轮询的从内存中将消息通过NIO发送到网络中 1 调用send方法 其实在调用 ...

  2. 【原创】Kafka producer原理 (Scala版同步producer)

    本文分析的Kafka代码为kafka-0.8.2.1.另外,由于Kafka目前提供了两套Producer代码,一套是Scala版的旧版本:一套是Java版的新版本.虽然Kafka社区极力推荐大家使用J ...

  3. 【原创】kafka producer源代码分析

        Kafka 0.8.2引入了一个用Java写的producer.下一个版本还会引入一个对等的Java版本的consumer.新的API旨在取代老的使用Scala编写的客户端API,但为了兼容性 ...

  4. 【转】Kafka producer原理 (Scala版同步producer)

    转载自:http://www.cnblogs.com/huxi2b/p/4583249.html     供参考 本文分析的Kafka代码为kafka-0.8.2.1.另外,由于Kafka目前提供了两 ...

  5. 关于Kafka producer管理TCP连接的讨论

    在Kafka中,TCP连接的管理交由底层的Selector类(org.apache.kafka.common.network)来维护.Selector类定义了很多数据结构,其中最核心的当属java.n ...

  6. 关于高并发下kafka producer send异步发送耗时问题的分析

    最近开发网关服务的过程当中,需要用到kafka转发消息与保存日志,在进行压测的过程中由于是多线程并发操作kafka producer 进行异步send,发现send耗时有时会达到几十毫秒的阻塞,很大程 ...

  7. Kafka producer介绍

    Kafka 0.9版本正式使用Java版本的producer替换了原Scala版本的producer.本文着重讨论新版本producer的设计原理以及基本的使用方法. 新版本Producer 首先明确 ...

  8. Kafka设计解析(十四)Kafka producer介绍

    转载自 huxihx,原文链接 Kafka producer介绍 Kafka 0.9版本正式使用Java版本的producer替换了原Scala版本的producer.本文着重讨论新版本produce ...

  9. .net core kafka 入门实例 一篇看懂

      kafka 相信都有听说过,不管有没有用过,在江湖上可以说是大名鼎鼎,就像天龙八部里的乔峰.国际惯例,先介绍生平事迹   简介 Kafka 是由 Apache软件基金会 开发的一个开源流处理平台, ...

随机推荐

  1. 普林斯顿数学指南(第一卷) (Timothy Gowers 著)

    第I部分 引论 I.1 数学是做什么的 I.2 数学的语言和语法 I.3 一些基本的数学定义 I.4 数学研究的一般目的 第II部分 现代数学的起源 II.1 从数到数系 II.2 几何学 II.3 ...

  2. JS中encodeURIComponent函数用php解码的代码

    JS中encodeURIComponent函数给中文编码后,如何用php解码?? 前提:编码前的中文可能是gbk,gb2312,utf-8等. 复制代码 代码如下: urldecode() iconv ...

  3. operator 重载内置运算符

    operator 关键字来重载内置运算符,或提供类或结构声明中的用户定义转换.它可以定义不同类型之间采用何种转化方式和转化的结果. operator用于定义类型转化时可采用2种方式,隐式转换(impl ...

  4. AIX系统日志

    1.系统错误日志 存放路径:/var/adm/ras/errlog 说明:该日志记录了系统所检测到的软硬件故障和错误,尤其对系统的硬件故障有很大的参考价值,是AIX提供的最有价值的日志之一, errl ...

  5. oracle之 ORA-12557: TNS: 协议适配器不可加载

    操作系统:windows 7数据库版本: 11.2.0.1问题描述:直接通过 sqlplus sys/oracle@10.10.100.109:1521/ysxt as sysdba 可以登录,但是通 ...

  6. jmeter一些插件下载网址

    JSONPathExtractor的插件下载 https://jmeter-plugins.org/wiki/JSONPathExtractor/

  7. 最全Pycharm教程(1)——定制外观

    http://blog.csdn.net/u013088062/article/details/50100121

  8. MOSSE(DSST)类和KCF类中滤波器推导结果不一致的解释

    首先要说明,DSST//BMVC2014类的CF是从MOSSE//CVPR2010模型得到的,是从信号的角度考虑问题,该类CF直接认为信号和滤波器之间存在相关的关系 而KCF//TPAMI2015类C ...

  9. 基于OLSR的路由协议实现Ad-Hoc组网

    一.软件包的安装 1. olsrd软件包的安装 libpthread_0.9.33.2-1_ar71xx.ipk olsrd_0.6.6.2-4_ar71xx.ipk 2. luci的安装 olsrd ...

  10. tgz的解压

    解压文件tgz 例如文件名为: yyyy.tgz 先使用GZIP解压为TAR文件 gzip -dv yyyy.tgz 同时解压后生成yyyy.tar文件 再使用tar解压yyyy.tar文件 tar ...