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. 无线模块 RXB12-315m TXB12-315M 应用

    近期有个产品用到这对模块,因为没有什么技术支持,就直接上机调试.測试结果为带障碍发射距离60米. 下面是应用的几个知识点: 1:编程操作.事实上比較简单,调制信号315M是模块自带的,不须要调制和解调 ...

  2. 转JMeter ----数据库 not allowed to connect to this MySQL

    测试的时候遇到报错:   Cannot create PoolableConnectionFactory (null,  message from server: "Host 'ceshiP ...

  3. ASP.NET AJAX入门系列(8):自定义异常处理

    在UpdatePanel控件异步更新时,如果有错误发生,默认情况下会弹出一个Alert对话框显示出错误信息,这对用户来说是不友好的,本文看一下如何在服务端和客户端脚本中自定义异常处理,翻译自官方文档. ...

  4. Java生成PDF文档(表格、列表、添加图片等)

    需要的两个包及下载地址: (1)iText.jar:http://download.csdn.net/source/296416 (2)iTextAsian.jar(用来进行中文的转换):http:/ ...

  5. 银行卡所属公司判断 参考自https://blog.csdn.net/well2049/article/details/79429130

    在网上找到了一个银行卡的验证,通过阿里的支付宝接口进行校验,能够准确识别是否存在,归属行,卡号类型是储蓄卡(DC)还是信用卡(CC). 接口api:需要传入的2个参数,卡号cardNo和cardBin ...

  6. 《JavaScript设计模式与开发》笔记 6.高阶函数

    1.函数作为参数传递 1.回调函数 2.Array.prototype.sort 2.函数作为返回值输出 1.判断数据的类型 3.高级函数的实现AOP 4.高阶函数的其他应用 1.currying 函 ...

  7. vi命令【方向键】变字母键的解决方法

    vi命令[方向键]变字母键的解决方法   最近在SSH下玩Debian发现了一个有趣的现象,就是在一些个别版本的Debian镜像下,使用vi命令时会出现键盘输出出错的现象,使用方向键时会变成C,D等字 ...

  8. django获取表单数据

    django获取单表数据的三种方式 v1 = models.Business.objects.all() # v1是QuerySet的列表 ,内部元素都是对象 v2 = models.Business ...

  9. HashSet的自定义实现

    package com.cy.collection; import java.util.HashMap; /** * HashSet自定义实现 * 是使用hashMap实现的 * 可以看一下HashS ...

  10. 学习-工作:GTD

    ylbtech-学习-工作:GTD GTD就是Getting Things Done的缩写,翻译过来就是“把事情做完”,是一个管理时间的方法.GTD的核心理念概括就是必须记录下来要做的事,然后整理安排 ...