在Java中使用Kafka
Producer部分
Producer在实例化后, 对外提供send方法, 用于将数据送到指定的topic和partition; 以及在退出时需要的destroy方法.
接口 KafkaProducer.java
import java.util.List;
import java.util.Properties; public interface KafkaProducer<D> { default void init() {
}
default void destroy() {
}
boolean send(String topic, D data);
boolean send(String topic, Integer partition, D data);
boolean send(String topic, List<D> dataList);
boolean send(String topic, Integer partition, List<D> dataList); /**
* 默认配置
*/
default Properties getDefaultProps() {
Properties props = new Properties();
props.put("acks", "1");
props.put("retries", 1);
props.put("batch.size", 16384);
props.put("linger.ms", 1);
props.put("buffer.memory", 32 * 1024 * 1024L);
return props;
}
}
参数说明
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
// The acks config controls the criteria under which requests are considered complete. The "all" setting we have specified will result in blocking on the full commit of the record, the slowest but most durable setting.
props.put("acks", "all");
// If the request fails, the producer can automatically retry, though since we have specified retries as 0 it won't. Enabling retries also opens up the possibility of duplicates (see the documentation on message delivery semantics for details).
props.put("retries", 0);
// The producer maintains buffers of unsent records for each partition. These buffers are of a size specified by the batch.size config. Making this larger can result in more batching, but requires more memory (since we will generally have one of these buffers for each active partition).
props.put("batch.size", 16384);
// By default a buffer is available to send immediately even if there is additional unused space in the buffer. However if you want to reduce the number of requests you can set linger.ms to something greater than 0. This will instruct the producer to wait up to that number of milliseconds before sending a request in hope that more records will arrive to fill up the same batch.
props.put("linger.ms", 1);
// 生产者缓冲大小,当缓冲区耗尽后,额外的发送调用将被阻塞。时间超过max.block.ms将抛出TimeoutException
props.put("buffer.memory", 33554432);
// The key.serializer and value.serializer instruct how to turn the key and value objects the user provides with their ProducerRecord into bytes. You can use the included ByteArraySerializer or StringSerializer for simple string or byte types.
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
实现 KafkaProducerImpl.java
import com.google.common.base.Strings;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.util.List;
import java.util.Map;
import java.util.Properties; public class KafkaProducerImpl<D> implements KafkaProducer<D> {
private static final Logger logger = LoggerFactory.getLogger(KafkaProducerImpl.class);
private final Producer<D, D> producer; public KafkaProducerImpl() {
Properties props = this.getDefaultProps();
props.put("bootstrap.servers", servers);
props.put("key.serializer", serializer);
props.put("value.serializer", serializer);
producer = new org.apache.kafka.clients.producer.KafkaProducer<>(props);
} @Override
public void destroy() {
if (producer != null) {
producer.close();
}
} @Override
public boolean send(String topic, D data) {
boolean isSuc = true;
try {
producer.send(new ProducerRecord<>(topic, data));
} catch (Exception e) {
isSuc = false;
logger.error(String.format("KafkaStringProducer send error.topic:[%s],data:[%s]", topic, data), e);
}
return isSuc;
} @Override
public boolean send(String topic, Integer partition, D data) {
boolean isSuc = true;
try {
producer.send(new ProducerRecord<>(topic, partition, null, data));
} catch (Exception e) {
isSuc = false;
logger.error(String.format("KafkaStringProducer send error.topic:[%s],data:[%s]", topic, data), e);
}
return isSuc;
} @Override
public boolean send(String topic, List<D> dataList) {
boolean isSuc = true;
try {
if (dataList != null) {
dataList.forEach(item -> producer.send(new ProducerRecord<>(topic, item)));
}
} catch (Exception e) {
isSuc = false;
logger.error(String.format("KafkaStringProducer send error.topic:[%s],dataList:[%s]", topic, dataList), e);
}
return isSuc;
} @Override
public boolean send(String topic, Integer partition, List<D> dataList) {
boolean isSuc = true;
try {
if (dataList != null) {
dataList.forEach(item -> producer.send(new ProducerRecord<>(topic, partition, null, item)));
}
} catch (Exception e) {
isSuc = false;
logger.error(String.format("KafkaStringProducer send error.topic:[%s],partition[%s],dataList:[%s]", topic, partition, dataList), e);
}
return isSuc;
}
}
Consumer 部分
Consumer 在实例化后, 负责将ConsumerListener添加到列表, 并订阅指定的topic, 启动一个阻塞的循环, 在收到消息后依次调用ConsumerListener进行处理
接口 KafkaConsumer.java
import java.util.Properties; public interface KafkaConsumer { default void init() {
} default void destroy() {
} void start(); /**
* 默认配置
*/
default Properties getDefaultProps() {
Properties props = new Properties();
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
props.put("session.timeout.ms", "30000");
return props;
}
}
参数说明
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "test");
// Setting enable.auto.commit means that offsets are committed automatically with a frequency controlled by the config auto.commit.interval.ms.
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
// The deserializer settings specify how to turn bytes into objects. For example, by specifying string deserializers, we are saying that our record's key and value will just be simple strings.
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
// This consumer is subscribing to the topics foo and bar as part of a group of consumers called test as configured with group.id.
consumer.subscribe(Arrays.asList("foo", "bar"));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(100);
for (ConsumerRecord<String, String> record : records)
System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
}
实现 KafkaConsumerImpl.java
import com.google.common.base.Strings;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.util.*; public class KafkaConsumerImpl<K, V> implements KafkaConsumer {
private static final Logger logger = LoggerFactory.getLogger(KafkaConsumerImpl.class);
private final List<KafkaConsumerListener<K, V>> consumerListeners = new ArrayList<>();
private Consumer<K, V> consumer;
private boolean running = true; private final int waitingTimeout = 100; public KafkaConsumerImpl(String topic, String groupId, String deserializer) {
Properties props = this.getDefaultProps();
props.put("group.id", groupId);
props.put("bootstrap.servers", servers);
props.put("key.deserializer", deserializer);
props.put("value.deserializer", deserializer);
consumer = new org.apache.kafka.clients.consumer.KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList(topic));
} public void setConsumerListeners(List<KafkaConsumerListener<K, V>> consumerListeners) {
synchronized (this) {
this.consumerListeners.clear();
if (null != consumerListeners && 0 != consumerListeners.size()) {
consumerListeners.forEach(this.consumerListeners::add);
}
}
} public void addConsumerListener(KafkaConsumerListener<K, V> consumerListener) {
synchronized (this) {
if (null != consumerListener && !this.consumerListeners.contains(consumerListener)) {
this.consumerListeners.add(consumerListener);
}
}
} public void removeConsumerListener(KafkaConsumerListener<K, V> consumerListener) {
synchronized (this) {
if (null != consumerListener && this.consumerListeners.contains(consumerListener)) {
this.consumerListeners.remove(consumerListener);
}
}
} @Override
public void init() {
this.start();
} @Override
public void destroy() {
running = false;
} @Override
public void start() {
new Thread(() -> {
while (running) {
ConsumerRecords<K, V> records = consumer.poll(waitingTimeout);
for (ConsumerRecord<K, V> record : records) {
if (consumerListeners != null) {
K key = record.key();
if (key == null)
consumerListeners.forEach(consumer -> consumer.consume(record.value()));
else
consumerListeners.forEach(consumer -> consumer.consume(record.key(), record.value()));
}
}
}
//should use consumer in different thread, or it will throw ConcurrentModificationException
if (consumer != null) {
try {
logger.info("start to close consumer.");
consumer.close();
} catch (Exception e) {
logger.error("close kafka consumer error.", e);
}
consumer = null;
}
}).start();
}
}
接口 KafkaConsumerListener.java
public interface KafkaConsumerListener<K, V> {
void consume(V value); default void consume(K key, V value) {
consume(value);
}
}
.
在Java中使用Kafka的更多相关文章
- 精选干货 在java中创建kafka
这个详细的教程将帮助你创建一个简单的Kafka生产者,该生产者可将记录发布到Kafka集群. 通过优锐课的java学习架构分享中,在本教程中,我们将创建一个简单的Java示例,该示例创建一个Kafka ...
- Java中的Unsafe类111
1.Unsafe类介绍 Unsafe类是在sun.misc包下,不属于Java标准.但是很多Java的基础类库,包括一些被广泛使用的高性能开发库都是基于Unsafe类开发的,比如Netty.Hadoo ...
- Java 中的纤程库 – Quasar
来源:鸟窝, colobu.com/2016/07/14/Java-Fiber-Quasar/ 如有好文章投稿,请点击 → 这里了解详情 最近遇到的一个问题大概是微服务架构中经常会遇到的一个问题: 服 ...
- spark streaming中维护kafka偏移量到外部介质
spark streaming中维护kafka偏移量到外部介质 以kafka偏移量维护到redis为例. redis存储格式 使用的数据结构为string,其中key为topic:partition, ...
- CentOS中配置Kafka集群
环境:三台虚拟机Host0,Host1,Host2 Host0:192.168.10.2 Host1: 192.168.10.3 Host2: 192.168.10.4 在三台虚拟机上配置zook ...
- 1.1 Introduction中 Apache Kafka™ is a distributed streaming platform. What exactly does that mean?(官网剖析)(博主推荐)
不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ Apache Kafka™ is a distributed streaming p ...
- CentOS7安装CDH 第九章:CDH中安装Kafka
相关文章链接 CentOS7安装CDH 第一章:CentOS7系统安装 CentOS7安装CDH 第二章:CentOS7各个软件安装和启动 CentOS7安装CDH 第三章:CDH中的问题和解决方法 ...
- SUSE中搭建kafka
搭建环境: JDK: java version 1.8.0_221 zookeeper:zookeeper-3.5.2 kafka: kafka-2.11-1.1.0 一.安装JDK 由于需要jav ...
- Springboot中使用kafka
注:kafka消息队列默认采用配置消息主题进行消费,一个topic中的消息只能被同一个组(groupId)的消费者中的一个消费者消费. 1.在pom.xml依赖下新添加一下kafka依赖ar包 < ...
随机推荐
- 【ContestHunter】【弱省胡策】【Round6】
KMP/DP+树链剖分+线段树/暴力 今天考的真是……大起大落…… String QwQ题意理解又出错了……(还是说一开始理解了,后来自己又忘了为什么是这样了?) 反正最后的结果就是……我当成:后面每 ...
- warning: LF will be replaced by CRLF in dubbo-demo-api/pom.xml.
今天使用git add .的时候出现了一个错误. 错误如下: 解决方案: $ rm -rf .git // 删除.git $ git config --global core.autocrlf fal ...
- C#如何使用SplitContainer控件实现上下分隔
C#如何使用SplitContainer控件实现上下分隔 Orientation 属性设置为Horizontal 完美世界 http://www.23cat.com/Contents_51864.ht ...
- iOS:简易的音视屏播放框架XYQPlayer
一.前缀 一直都想好好学学音视频这方面的知识,抽了几个周末参考一些资料,尝试着写了一个简易的音视频播放框架,支持音视频播放.视频截图.音乐缓存,其实吧,也就是尽可能的封装罢了,方便以后自己使用.目前只 ...
- Android -- 在xml文件中定义drawable数组
Xml <string-array name="images"> <item>@drawable/image1</item> <item& ...
- 在centos7.4上安装mysql5.5
from: https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-centos-7
- (NGUI)UISprite 切换图集
UISprite是可以使用代码动态切换图集的 using UnityEngine; using System.Collections; public class SpriteAtlasTest : M ...
- Pandas DataFrame笔记
1.属性方式,可以用于列,不能用于行 2.可以用整数切片选择行,但不能用单个整数索引(当索引不是整数时) 3.直接索引可以使用列.列集合,但不能用索引名索引行 用iloc取行,得到的series: d ...
- C++ 容器元素的存储和获取
1.存储对象,存储的是对象的副本,并不是原对象.2.获取对象,获取的是对象的引用,为什么要这样设计?a.存储对象只发生一次,而获取对象往往会有多次,获取对象,如果每次都返回对象的副本,这个开销很大.b ...
- 轻量级分布式文件系统FastDFS使用安装说明手册(新手入门级)
轻量级分布式文件系统FastDFS使用安装说明手册(新手入门级) 实验室所在的课题组以研究云计算为主,但所有的研究都是在基于理论的凭空想像,缺少分布式环境的平台的实践,云计算神马的都是浮云了.因此,我 ...