kafka producer自定义partitioner和consumer多线程
为了更好的实现负载均衡和消息的顺序性,Kafka Producer可以通过分发策略发送给指定的Partition。Kafka Java客户端有默认的Partitioner,平均的向目标topic的各个Partition中生产数据,如果想要控制消息的分发策略,有两种方式,一种是在发送前创建ProducerRecord时指定分区(针对单个消息),另一种就是就是根据Key自己写算法。继承Partitioner接口,实现其partition方法。并且配置启动参数 props.put("partitioner.class","com.example.demo.MyPartitioner"),示例代码如下:
自定义的partitoner
package com.example.demo; import java.util.Map; import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster; public class MyPartitioner implements Partitioner { @Override
public void configure(Map<String, ?> configs) { } @Override
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
if (Integer.parseInt((String)key)%3==1)
return 0;
else if (Integer.parseInt((String)key)%3==2)
return 1;
else return 2;
} @Override
public void close() { } }
producer类中指定partitioner.class
package com.example.demo; import java.util.Properties; import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord; public class MyProducer { public static void main(String[] args) {
Properties props = new Properties();
props.put("bootstrap.servers", "192.168.1.124:9092");
props.put("acks", "all");
props.put("retries", 0);
props.put("batch.size", 16384);
props.put("linger.ms", 1);
props.put("partitioner.class", "com.example.demo.MyPartitioner");
props.put("buffer.memory", 33554432);
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); Producer<String, String> producer = new KafkaProducer<>(props);
for (int i = 0; i < 100; i++)
producer.send(new ProducerRecord<String, String>("powerTopic", Integer.toString(i), Integer.toString(i))); producer.close(); }
}
测试consumer
package com.example.demo; import java.util.Arrays;
import java.util.Properties; import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer; public class MyAutoCommitConsumer { public static void main(String[] args) {
Properties props = new Properties();
props.put("bootstrap.servers", "192.168.1.124:9092");
props.put("group.id", "test");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
@SuppressWarnings("resource")
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("powerTopic"));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(100);
for (ConsumerRecord<String, String> record : records)
System.out.printf("partition = %d,offset = %d, key = %s, value = %s%n",record.partition(), record.offset(), record.key(), record.value());
}
}
}
启动zookeeper和kafka,使用命令行新建一个 3个partition的topic:powerTopic,为了方便查看结果,将producer的循环次数设置为15,运行consumer和producer代码,效果如下:

虽然我们有三个分区,但是我们group组中只有一个消费者,所以三个分区的消息被这个消费者顺序消费,下面我们实现一个消费者组,示例代码如下:
ConsumerThread类
package com.example.demo; import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer; import java.util.Arrays;
import java.util.Properties; public class ConsumerThread implements Runnable {
private KafkaConsumer<String,String> kafkaConsumer;
private final String topic; public ConsumerThread(String brokers,String groupId,String topic){
Properties properties = buildKafkaProperty(brokers,groupId);
this.topic = topic;
this.kafkaConsumer = new KafkaConsumer<String, String>(properties);
this.kafkaConsumer.subscribe(Arrays.asList(this.topic));
} private static Properties buildKafkaProperty(String brokers,String groupId){
Properties properties = new Properties();
properties.put("bootstrap.servers", brokers);
properties.put("group.id", groupId);
properties.put("enable.auto.commit", "true");
properties.put("auto.commit.interval.ms", "1000");
properties.put("session.timeout.ms", "30000");
properties.put("auto.offset.reset", "earliest");
properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
return properties;
} @Override
public void run() {
while (true){
ConsumerRecords<String,String> consumerRecords = kafkaConsumer.poll(100);
for(ConsumerRecord<String,String> item : consumerRecords){
System.out.println(Thread.currentThread().getName());
System.out.printf("partition = %d,offset = %d, key = %s, value = %s%n",item.partition(), item.offset(), item.key(), item.value());
}
}
}
}
ConsumerGroup类
package com.example.demo; import java.util.ArrayList;
import java.util.List; public class ConsumerGroup {
private List<ConsumerThread> consumerThreadList = new ArrayList<ConsumerThread>(); public ConsumerGroup(String brokers,String groupId,String topic,int consumerNumber){
for(int i = 0; i< consumerNumber;i++){
ConsumerThread consumerThread = new ConsumerThread(brokers,groupId,topic);
consumerThreadList.add(consumerThread);
}
} public void start(){
for (ConsumerThread item : consumerThreadList){
Thread thread = new Thread(item);
thread.start();
}
}
}
消费者组启动类ConsumerGroupMain
package com.example.demo;
public class ConsumerGroupMain {
public static void main(String[] args){
String brokers = "192.168.1.124:9092";
String groupId = "group01";
String topic = "powerTopic";
int consumerNumber = 3;
ConsumerGroup consumerGroup = new ConsumerGroup(brokers,groupId,topic,consumerNumber);
consumerGroup.start();
}
}
启动消费者和生产者,可以看到不同的分区是不同的线程去执行的效果如下:

kafka producer自定义partitioner和consumer多线程的更多相关文章
- 【原创】Kafka Consumer多线程实例
Kafka 0.9版本开始推出了Java版本的consumer,优化了coordinator的设计以及摆脱了对zookeeper的依赖.社区最近也在探讨正式用这套consumer API替换Scala ...
- 【原创】Kafka Consumer多线程实例续篇
在上一篇<Kafka Consumer多线程实例>中我们讨论了KafkaConsumer多线程的两种写法:多KafkaConsumer多线程以及单KafkaConsumer多线程.在第二种 ...
- Kettle安装Kafka Consumer和Kafka Producer插件
1.从github上下载kettle的kafka插件,地址如下 Kafka Consumer地址: https://github.com/RuckusWirelessIL/pentaho-kafka- ...
- 【原创】kafka producer源代码分析
Kafka 0.8.2引入了一个用Java写的producer.下一个版本还会引入一个对等的Java版本的consumer.新的API旨在取代老的使用Scala编写的客户端API,但为了兼容性 ...
- 玩转Kafka的生产者——分区器与多线程
上篇文章学习kafka的基本安装和基础概念,本文主要是学习kafka的常用API.其中包括生产者和消费者, 多线程生产者,多线程消费者,自定义分区等,当然还包括一些避坑指南. 首发于个人网站:链接地址 ...
- kafka producer实例
1. 定义要发送的消息User POJO package lenmom.kafkaproducer; public class User { public String name; public in ...
- Kafka Producer接口
参考, https://cwiki.apache.org/confluence/display/KAFKA/0.8.0+Producer+Example http://kafka.apache.org ...
- 详解Kafka Producer
上一篇文章我们主要介绍了什么是 Kafka,Kafka 的基本概念是什么,Kafka 单机和集群版的搭建,以及对基本的配置文件进行了大致的介绍,还对 Kafka 的几个主要角色进行了描述,我们知道,不 ...
- Kafka Producer相关代码分析【转】
来源:https://www.zybuluo.com/jewes/note/63925 @jewes 2015-01-17 20:36 字数 1967 阅读 1093 Kafka Producer相关 ...
随机推荐
- 设计模式18:Observer 观察者模式(行为型模式)
Observer 观察者模式(行为型模式) 动机(Motivation) 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有依赖对象(观察者对象) ...
- spring mvc注解@RequestMapping
1.url路径映射 基本功能 2.窄化请求映射 根路径+子路径 注意setViewName的路径. 3.限制http请求方法 get和 post 如果是get
- 配置hive环境以及mysql配置后必须做
1.先在主节点上安装阿里云配置(看别的文档) 2.把需要的两个jar包加入进来(放到hadoop用户目录下面即可即/home/hadoop/) mysql-connector-java-5.1.47. ...
- VCS简介
VCS -Version Control System 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统. 特征 1.记录文件的所有历史变化 2.随时可恢复到任何一个历史状 ...
- C# 字符,字符串和文本处理。
1. 字符: 在.net中 字符是表示成16为Unicode代码值.每个字符都是System.Char结构(一个值类型)的实例. public class StringTempte { public ...
- jsonp的使用记录
最近前端的同事说要写一个手机查看的html5页面,需要我提供数据. 这个很ok啊,立马写了个服务返回数据.但是对方调用不了,因为跨域了. 返回错误如下: Failed to load xxxxxx: ...
- CS0012 类型“DbContext”在未引用的程序集中定义。必须添加对程序集“EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”的引用。 Repository E:\项目\wx\Repository\DbContextFac
严重性 代码 说明 项目 文件 行 禁止显示状态错误 CS0012 类型“DbContext”在未引用的程序集中定义.必须添加对程序集“EntityFramework, Version=6.0.0.0 ...
- 如何用Python做Web开发?——Django环境配置
用Python做Web开发,Django框架是个非常好的起点.如何从零开始,配置好Django开发环境呢?本文带你一步步无痛上手. 概念 最近有个词儿很流行,叫做“全栈”(full stack ...
- is 与 == 的区别;小数据池; 编码与解码
1, is 与 == 的区别 == 比较的是两边的值 is 比较的是两边的地址 id () 2,小数据池(在终端中) 数字小数据池的范围 -5 ~ 256 字符串中如果有特殊字符他们的内存地址 ...
- [AIR] AIR将数据保存并导出为Excel
package { import flash.display.Sprite; import flash.events.MouseEvent; import flash.filesystem.File; ...