hadoop151 | hadoop152 | hadoop153 |
---|---|---|
zookeeper | zookeeper | zookeeper |
kafka | kafka | kafka |
第一步:将 kafka_2.11-0.11.0.0.tgz 上传到服务器并解压
第二步:在kafka目录下创建data目录
第三步:修改 kafka 目录下的 config 目录下的 server.properties 文件(具体配置可参考:https://kafka.apache.org/28/documentation.html#configuration)
#broker 的全局唯一编号,不能重复
broker.id=1
#删除 topic 功能使能
delete.topic.enable=true
#处理网络请求的线程数量
num.network.threads=3
#用来处理磁盘 IO 的现成数量
num.io.threads=8
#发送套接字的缓冲区大小
socket.send.buffer.bytes=102400
#接收套接字的缓冲区大小
socket.receive.buffer.bytes=102400
#请求套接字的缓冲区大小
socket.request.max.bytes=104857600
#kafka 运行日志存放的路径
log.dirs=/opt/module/kafka/logs
#topic 在当前 broker 上的分区个数
num.partitions=1
#用来恢复和清理 data 下数据的线程数量
num.recovery.threads.per.data.dir=1
#segment 文件保留的最长时间,超时将被删除
log.retention.hours=168
#配置连接 Zookeeper 集群地址
zookeeper.connect=hadoop151:2181,hadoop152:2181,hadoop153:2181
第四步:将kafka整个文件分发到另外两台服务器上
第五步:将 hadoop152和hadoop153 服务器中的 server.properties 文件中的 broker.id 参数分别修改成 2和3
第六步:将三台服务器上的 zookeeper 启动
第七步:将三台服务器上的 kafka 启动
#启动kafka
bin/kafka-server-start.sh -daemon config/server.properties
启停命令
# 启动
{kafka_home目录}/bin/kafka-server-start.sh -daemon server.properties文件目录及文件名
# 停止
{kafka_home目录}/bin/kafka-server-stop.sh
参数 | 描述 |
---|---|
–bootstrap-server |
连接的 Kafka Broker 主机名称和端口号。 |
–topic |
操作的 topic 名称。 |
–create | 创建主题。 |
–delete | 删除主题。 |
–alter | 修改主题。 |
–list | 查看所有主题。 |
–describe | 查看主题详细描述。 |
–partitions |
设置分区数。 |
–replication-factor |
设置分区副本。 |
–config |
更新系统默认的配置。 |
# 查看当前服务器中的所有 topic(--list)
bin/kafka-topics.sh --bootstrap-server hadoop151:9092,hadoop152:9092,hadoop153:9092 --list
# 查看first 主题的详情
bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --describe --topic first
# 创建 topic
bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --create --partitions 1 --replication-factor 2 --topic first
# 修改分区数(注意:分区数只能增加,不能减少)
bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --alter --topic first --partitions 3
# 删除topic
bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --delete --topic first
参数 | 描述 |
---|---|
–bootstrap-server |
连接的 Kafka Broker 主机名称和端口号。 |
–topic |
操作的 topic 名称。 |
# 发送消息
bin/kafka-console-producer.sh \
--bootstrap-server hadoop151:9092,hadoop152:9092,hadoop153:9092 \
--topic fzk
使用:生产者消费程序中使用参数
官网:https://kafka.apache.org/28/documentation.html#producerconfigs
参数名称 | 描述 |
---|---|
bootstrap.servers | 生产者连接集群所需的 broker 地址清单。 例如 hadoop102:9092,hadoop103:9092,hadoop104:9092,可以设置 1 个或者多个,中间用逗号隔开。注意这里并非需要所有的 broker 地址,因为生产者从给定的 broker里查找到其他 broker 信息。 |
key.serializer 和 value.serializer | 指定发送消息的 key 和 value 的序列化类型。一定要写全类名。 |
buffer.memory | RecordAccumulator 缓冲区总大小,默认 32m(33554432)。 |
batch.size | 缓冲区一批数据最大值,默认 16k(16384)。适当增加该值,可以提高吞吐量,但是如果该值设置太大,会导致数据传输延迟增加。 |
linger.ms | 如果数据迟迟未达到 batch.size,sender 等待 linger.time之后就会发送数据。单位 ms,默认值是 0ms,表示没有延迟。生产环境建议该值大小为 5-100ms 之间。 |
acks | 0:生产者发送过来的数据,不需要等数据落盘应答。1:生产者发送过来的数据,Leader 收到数据后应答。-1(all):生产者发送过来的数据,Leader+和 isr 队列里面的所有节点收齐数据后应答。默认值是-1,-1 和 all 是等价的。 |
max.in.flight.requests.per.connection | 允许最多没有返回 ack 的次数,默认为 5,开启幂等性要保证该值是 1-5 的数字。 |
retries | 当消息发送出现错误的时候,系统会重发消息。retries表示重试次数。默认是 int 最大值,2147483647。如果设置了重试,还想保证消息的有序性,需要设置MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION=1否则在重试此失败消息的时候,其他的消息可能发送成功了。 |
retry.backoff.ms | 两次重试之间的时间间隔,默认是 100ms。 |
enable.idempotence | 是否开启幂等性,默认 true,开启幂等性。重复数据的判断标准:具有 |
compression.type | 生产者发送的所有数据的压缩方式。默认是 none,也就是不压缩。支持压缩类型:none、gzip、snappy、lz4 和 zstd。 |
创建Maven工程,引入依赖(pom.xml)
<dependencies>
<dependency>
<groupId>org.apache.kafkagroupId>
<artifactId>kafka-clientsartifactId>
<version>2.8.1version>
dependency>
dependencies>
public class MyProducer {
public static void main(String[] args) {
//1、编写配置
Properties properties = new Properties();
//kafka 集群,bootstrap.servers
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop151:9092,hadoop152:9092,hadoop153:9092");
//ack应答级别
properties.put(ProducerConfig.ACKS_CONFIG, "all");
//重试次数
properties.put(ProducerConfig.RETRIES_CONFIG, 1);
//批次大小
properties.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
//等待时间
properties.put(ProducerConfig.LINGER_MS_CONFIG, 1);
//RecordAccumulator 缓冲区大小
properties.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 33554432);
//key值序列化
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
//value值序列化
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
//2、创建生产者(producer)
KafkaProducer<String, String> producer = new KafkaProducer<String, String>(properties);
for (int i = 0; i < 10; i++) {
//3、发送消息
producer.send(new ProducerRecord<String, String>("fzk", "fzk -- " + i));
}
//4、关闭资源
if(producer != null){
producer.close();
}
}
}
public class CallbackProducer {
public static void main(String[] args) {
//1、配置参数
Properties properties = new Properties();
//kafka集群
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop151:9092,hadoop152:9092,hadoop153:9092");
//key值序列化
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
//value值序列化
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
//2、创建生产者(Producer)
KafkaProducer<String, String> producer = new KafkaProducer<String, String>(properties);
for (int i = 0; i < 10; i++) {
//3、发送消息(带回调函数,Callback)
producer.send(new ProducerRecord<String, String>("fzk", "fzk -- " + i), new Callback() {
public void onCompletion(RecordMetadata recordMetadata, Exception e) {
if (e == null){
//输出回调信息,(RecordMetadata:回调函数的信息)
System.out.println(recordMetadata.partition() + " --- " + recordMetadata.offset());
}
}
});
}
//4、关闭资源
if (producer != null){
producer.close();
}
}
}
public class MyProducer {
public static void main(String[] args) {
//1、编写配置
Properties properties = new Properties();
//kafka 集群,broker-list
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop151:9092,hadoop152:9092,hadoop153:9092");
//ack应答级别
properties.put(ProducerConfig.ACKS_CONFIG, "all");
//重试次数
properties.put(ProducerConfig.RETRIES_CONFIG, 1);
//批次大小
properties.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
//等待时间
properties.put(ProducerConfig.LINGER_MS_CONFIG, 1);
//RecordAccumulator 缓冲区大小
properties.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 33554432);
//key值序列化
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
//value值序列化
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
//2、创建生产者(producer)
KafkaProducer<String, String> producer = new KafkaProducer<String, String>(properties);
for (int i = 0; i < 10; i++) {
//3、发送消息
// 异步发送
producer.send(new ProducerRecord<String, String>("fzk", "fzk -- " + i));
// 同步发送,后面加【.get()】
producer.send(new ProducerRecord<String, String>("fzk", "fzk -- " + i)).get();
}
//4、关闭资源
if(producer != null){
producer.close();
}
}
}
第一步:自定义分区类
public class MyPartitioner implements Partitioner {
//分区方法
public int partition(String s, Object o, byte[] bytes, Object o1, byte[] bytes1, Cluster cluster) {
//分区逻辑
//返回分区数
return 分区数;
}
//关闭
public void close() {
}
//配置信息
public void configure(Map<String, ?> map) {
}
}
第二步:使用自定义分区
public class PartitionerProducer {
public static void main(String[] args) {
//1、配置参数
Properties properties = new Properties();
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop151:9092,hadoop152:9092,hadoop153:9092");
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
//使用自定义分区,value值:自定义分区类的全限定类名
properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG, "com.itfzk.kafka.partitioner.MyPartitioner");
//2、创建生产者(Producer)
KafkaProducer<String, String> producer = new KafkaProducer<String, String>(properties);
for (int i = 0; i < 10; i++) {
//3、发送消息(带回调函数)
producer.send(new ProducerRecord<String, String>("fzk", "fzk -- " + i), new Callback() {
public void onCompletion(RecordMetadata recordMetadata, Exception e) {
if (e == null){
//输出回调信息,(RecordMetadata:回调函数的信息)
System.out.println(recordMetadata.partition() + " --- " + recordMetadata.offset());
}
}
});
}
//4、关闭资源
if (producer != null){
producer.close();
}
}
}
Producer 在使用事务功能前,必须先自定义一个唯一的 transactional.id。有了 transactional.id,即使客户端挂掉了,它重启后也能继续处理未完成的事务
事务api
// 初始化事务
void initTransactions();
// 开启事务
void beginTransaction() throws ProducerFencedException;
// 在事务内提交已经消费的偏移量(主要用于消费者)
void sendOffsetsToTransaction(Map<TopicPartition, OffsetAndMetadata> offsets, String consumerGroupId) throws
ProducerFencedException;
// 提交事务
void commitTransaction() throws ProducerFencedException;
// 放弃事务(类似于回滚事务的操作)
void abortTransaction() throws ProducerFencedException;
public class MyProducer {
public static void main(String[] args) {
//1、编写配置
Properties properties = new Properties();
//kafka 集群,bootstrap.servers
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop151:9092,hadoop152:9092,hadoop153:9092");
//ack应答级别
properties.put(ProducerConfig.ACKS_CONFIG, "all");
//key值序列化
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
//value值序列化
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
// 1、设置事务 id(必须),事务 id 任意起名
properties.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG, "transaction_id_0");
KafkaProducer<String, String> kafkaProducer = new KafkaProducer<String, String>(properties);
// 2、初始化事务
kafkaProducer.initTransactions();
// 3、开启事务
kafkaProducer.beginTransaction();
try {
for (int i = 0; i < 10; i++) {
//4、发送消息
kafkaProducer.send(new ProducerRecord<String, String>("fzk", "fzk -- " + i));
// 5、提交事务
kafkaProducer.commitTransaction();
}
} catch (Exception e) {
// 6、终止事务
kafkaProducer.abortTransaction();
} finally {
if(kafkaProducer != null){
kafkaProducer.close();
}
}
}
}
使用:kafka配置(server.properties)
官网:https://kafka.apache.org/28/documentation.html#brokerconfigs
参数名称 | 描述 |
---|---|
replica.lag.time.max.ms | ISR 中,如果 Follower 长时间未向 Leader 发送通信请求或同步数据,则该 Follower 将被踢出 ISR。该时间阈值,默认 30s。 |
auto.leader.rebalance.enable | 默认是 true。 自动Leader Partition 平衡。 |
leader.imbalance.per.broker.percentage | 默认是 10%。每个 broker 允许的不平衡的 leader的比率。如果每个 broker 超过了这个值,控制器会触发 leader 的平衡。 |
leader.imbalance.check.interval.seconds | 默认值 300 秒。检查 leader 负载是否平衡的间隔时间。 |
log.segment.bytes | Kafka 中 log 日志是分成一块块存储的,此配置是指 log 日志划分成块的大小,默认值 1G。 |
log.index.interval.bytes | 默认 4kb,kafka 里面每当写入了 4kb 大小的日志(.log),然后就往 index 文件里面记录一个索引。 |
log.retention.hours | Kafka 中数据保存的时间,默认 7 天。 |
log.retention.minutes | Kafka 中数据保存的时间,分钟级别,默认关闭。 |
log.retention.ms | Kafka 中数据保存的时间,毫秒级别,默认关闭。 |
log.retention.check.interval.ms | 检查数据是否保存超时的间隔,默认是 5 分钟。 |
log.retention.bytes | 默认等于-1,表示无穷大。超过设置的所有日志总大小,删除最早的 segment。 |
log.cleanup.policy | 默认是 delete,表示所有数据启用删除策略;如果设置值为 compact,表示所有数据启用压缩策略。 |
num.io.threads | 默认是 8。负责写磁盘的线程数。整个参数值要占总核数的 50%。 |
num.replica.fetchers | 副本拉取线程数,这个参数占总核数的 50%的 1/3 |
num.network.threads | 默认是 3。数据传输线程数,这个参数占总核数的50%的 2/3 。 |
log.flush.interval.messages | 强制页缓存刷写到磁盘的条数,默认是 long 的最大值,9223372036854775807。一般不建议修改,交给系统自己管理。 |
log.flush.interval.ms | 每隔多久,刷数据到磁盘,默认是 null。一般不建议修改,交给系统自己管理。 |
参数 | 描述 |
---|---|
–bootstrap-server |
连接的 Kafka Broker 主机名称和端口号。 |
–topic |
操作的 topic 名称。 |
–from-beginning | 从头开始消费。 |
–group |
指定消费者组名称。 |
# 消费 fzk 主题中的数据
bin/kafka-console-consumer.sh \
--bootstrap-server hadoop151:9092,hadoop152:9092,hadoop153:9092 \
--topic fzk
参数名称 | 描述 |
---|---|
bootstrap.servers | 向 Kafka 集群建立初始连接用到的 host/port 列表。 |
key.deserializer 和value.deserializer | 指定接收消息的 key 和 value 的反序列化类型。一定要写全类名。 |
group.id | 标记消费者所属的消费者组。 |
enable.auto.commit | 默认值为 true,消费者会自动周期性地向服务器提交偏移量。 |
auto.commit.interval.ms | 如果设置了 enable.auto.commit 的值为 true, 则该值定义了消费者偏移量向Kafka 提交的频率,默认 5s。 |
auto.offset.reset | 当 Kafka 中没有初始偏移量或当前偏移量在服务器中不存在(如,数据被删除了),该如何处理? earliest:自动重置偏移量到最早的偏移量。 latest:默认,自动重置偏移量为最新的偏移量。 none:如果消费组原来的(previous)偏移量不存在,则向消费者抛异常。 anything:向消费者抛异常。 |
offsets.topic.num.partitions | consumer_offsets 的分区数,默认是 50 个分区。 |
heartbeat.interval.ms | Kafka 消费者和 coordinator 之间的心跳时间,默认 3s。该条目的值必须小于 session.timeout.ms , 也不应该高于session.timeout.ms 的 1/3。 |
session.timeout.ms | Kafka 消费者和 coordinator 之间连接超时时间,默认 45s。超过该值,该消费者被移除,消费者组执行再平衡。 |
max.poll.interval.ms | 消费者处理消息的最大时长,默认是 5 分钟。超过该值,该消费者被移除,消费者组执行再平衡。 |
fetch.min.bytes | 默认 1 个字节。消费者获取服务器端一批消息最小的字节数。 |
fetch.max.wait.ms | 默认 500ms。如果没有从服务器端获取到一批数据的最小字节数。该时间到,仍然会返回数据。 |
fetch.max.bytes | 默认Default: 52428800(50 m)。消费者获取服务器端一批消息最大的字节数。如果服务器端一批次的数据大于该值(50m)仍然可以拉取回来这批数据,因此,这不是一个绝对最大值。一批次的大小受 message.max.bytes ( broker config)or max.message.bytes (topic config)影响。 |
max.poll.records | 一次 poll 拉取数据返回消息的最大条数,默认是 500 条。 |
partition.assignment.strategy | 消 费 者 分 区 分 配 策 略 , 默 认 策 略 是 Range +CooperativeSticky。Kafka 可以同时使用多个分区分配策略。可以选择的策略包括: Range 、 RoundRobin(轮训) 、 Sticky(粘性分区) 、CooperativeSticky |
public class MyConsumer {
public static void main(String[] args) {
//1、配置信息
Properties properties = new Properties();
//kafka集群
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop151:9092,hadoop152:9092,hadoop153:9092");
//是否开启自动提交 offset 功能
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
//自动提交 offset 的时间间隔
properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
//key值的反序列化
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
//key值的反序列化
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
//消费者组
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "group_test");
//2、创建消费者对象(Consumer)
KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);
//3、订阅主题,可订阅多个
consumer.subscribe(Arrays.asList("fff", "zzz", "kkk"));
while (true){
//4、拉取订阅的消息
ConsumerRecords<String, String> consumerRecords = consumer.poll(100);
//打印拉取到的消息
for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
System.out.println(consumerRecord.key() + " --- " + consumerRecord.value());
}
}
}
}
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
consumer.commitAsync()
public class ASyncCommitConsumer {
public static void main(String[] args) {
//1、配置信息
Properties properties = new Properties();
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop151:9092,hadoop152:9092,hadoop153:9092");
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "group_test");
//关闭自动提交 offset 功能
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
//2、创建消费者对象(Consumer)
KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);
//3、订阅主题,可订阅多个
consumer.subscribe(Arrays.asList("fff", "zzz", "kkk"));
while (true){
//4、拉取订阅的消息
ConsumerRecords<String, String> consumerRecords = consumer.poll(100);
//打印拉取到的消息
for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
System.out.println(consumerRecord.key() + " --- " + consumerRecord.value());
}
//5、异步提交
consumer.commitAsync(new OffsetCommitCallback() {
public void onComplete(Map<TopicPartition, OffsetAndMetadata> map, Exception e) {
if (e != null){
System.out.println("提交成功 -- " + map);
}
}
});
}
}
}
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
consumer.commitSync();
public class SyncCommitConsumer {
public static void main(String[] args) {
//1、配置信息
Properties properties = new Properties();
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop151:9092,hadoop152:9092,hadoop153:9092");
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "group_test");
//关闭自动提交 offset 功能
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
//2、创建消费者对象(Consumer)
KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);
//3、订阅主题,可订阅多个
consumer.subscribe(Arrays.asList("fff", "zzz", "kkk"));
while (true){
//4、拉取订阅的消息
ConsumerRecords<String, String> consumerRecords = consumer.poll(100);
//打印拉取到的消息
for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
System.out.println(consumerRecord.key() + " --- " + consumerRecord.value());
}
//5、同步提交,当前线程会阻塞直到 offset 提交成功
consumer.commitSync();
}
}
}
public class MyConsumer {
public static void main(String[] args) {
Properties properties = new Properties();
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop151:9092,hadoop152:9092,hadoop153:9092");
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "group_test");
KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);
consumer.subscribe(Arrays.asList("fff", "zzz", "kkk"));
// 获取消费者分区分配信息
List<PartitionInfo> partitionInfoList = consumer.partitionsFor(topic);
// 遍历所有分区,并指定 offset 从 1700 的位置开始消费
for (TopicPartition tp: partitionInfoList) {
consumer.seek(tp, 1700);
}
while (true){
ConsumerRecords<String, String> consumerRecords = consumer.poll(100);
for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
System.out.println(consumerRecord.key() + " --- " + consumerRecord.value());
}
}
}
}
public class MyConsumer {
public static void main(String[] args) {
Properties properties = new Properties();
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop151:9092,hadoop152:9092,hadoop153:9092");
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "group_test");
String topic = "fff";
KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);
consumer.subscribe(Arrays.asList("fff"));
// 1、获取开始 partition offset
HashMap<TopicPartition, Long> partitionTimeHashMap = Maps.newHashMap();
// 获取分区信息
List<PartitionInfo> partitionInfoList = consumer.partitionsFor(topic);
for (PartitionInfo partitionInfo : partitionInfoList) {
// 设置当前时间前一天的每个分区的offset
partitionTimeHashMap.put(new TopicPartition(partitionInfo.topic(), partitionInfo.partition()),
System.currentTimeMillis() - 1 * 24 * 3600 * 1000);
}
// 获取分区的开始 offset 信息
Map<TopicPartition, OffsetAndTimestamp> startTimeStampSearch = consumer.offsetsForTimes(partitionTimeHashMap);
// 2、设置分区读取消息的偏移量
startTimeStampSearch.forEach((topicPartition, offsetAndTimestamp) -> {
if (offsetAndTimestamp != null) {
consumer.seek(topicPartition, offsetAndTimestamp.offset());
}
});
// 3、消费消息
while (true){
ConsumerRecords<String, String> consumerRecords = consumer.poll(100);
for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
System.out.println(consumerRecord.key() + " --- " + consumerRecord.value());
}
}
}
}
org.apache.kafka.clients.producer.ProducerInterceptor
,其定义的方法包括:需求
实现
添加时间戳(拦截器)
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 TimeInterceptor implements ProducerInterceptor<String, String> {
//获取配置信息和初始化数据时调用
@Override
public void configure(Map<String, ?> map) {
}
//该方法封装进 KafkaProducer.send 方法中,即它运行在用户主线程中
@Override
public ProducerRecord<String, String> onSend(ProducerRecord<String, String> producerRecord) {
//在消息(value)前面添加时间戳
ProducerRecord<String, String> record = new ProducerRecord<String, String>(
producerRecord.topic(),
producerRecord.partition(),
producerRecord.key(),
System.currentTimeMillis() + " -- " + producerRecord.value());
return record;
}
//该方法会在消息从 RecordAccumulator 成功发送到 Kafka Broker 之后,或者在发送过程中失败时调用
@Override
public void onAcknowledgement(RecordMetadata recordMetadata, Exception e) {
}
//关闭 interceptor,主要用于执行一些资源清理工作
@Override
public void close() {
}
}
统计发送成功及失败的数量并打印(拦截器)
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 CountInterceptor implements ProducerInterceptor<String, String> {
private int successCount = 0;
private int errorCount = 0;
//获取配置信息和初始化数据时调用
@Override
public void configure(Map<String, ?> map) {
}
//该方法封装进 KafkaProducer.send 方法中,即它运行在用户主线程中
@Override
public ProducerRecord<String, String> onSend(ProducerRecord<String, String> producerRecord) {
return producerRecord;
}
//该方法会在消息从 RecordAccumulator 成功发送到 Kafka Broker 之后,或者在发送过程中失败时调用
@Override
public void onAcknowledgement(RecordMetadata recordMetadata, Exception e) {
//统计发送成功及失败的数量
if(e == null){
successCount++;
}else{
errorCount++;
}
}
//关闭 interceptor,主要用于执行一些资源清理工作
@Override
public void close() {
//打印发送成功及失败的数量
System.out.println("成功数量:" + successCount);
System.out.println("失败数量:" + errorCount);
}
}
生产者
import org.apache.kafka.clients.producer.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class InterceptorProducer {
public static void main(String[] args) {
//1、配置参数
Properties properties = new Properties();
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop151:9092,hadoop152:9092,hadoop153:9092");
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
//自定义拦截器配置(两个拦截器组成拦截器链)
List<String> interceptorList = new ArrayList<String>();
interceptorList.add("com.itfzk.kafka.interceptor.TimeInterceptor");
interceptorList.add("com.itfzk.kafka.interceptor.CountInterceptor");
properties.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, interceptorList);
//2、创建生产者(Producer)
KafkaProducer<String, String> producer = new KafkaProducer<String, String>(properties);
for (int i = 0; i < 10; i++) {
//3、发送消息
producer.send(new ProducerRecord<String, String>("fzk", "fzk -- " + i));
}
//4、关闭资源
if (producer != null){
producer.close();
}
}
}
安装
第一步:修改 kafka 启动命令(kafka-server-start.sh)
if [ "x$KAFKA_HEAP_OPTS" = "x" ]; then
export JMX_PORT="9999"
export KAFKA_HEAP_OPTS="-server -Xms2G -Xmx2G -XX:PermSize=128m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=8 -XX:ConcGCThreads=5 -XX:InitiatingHeapOccupancyPercent=70"
#export KAFKA_HEAP_OPTS="-Xmx1G -Xms1G"
fi
第二步:将 kafka-server-start.sh 分发到其他服务器
第三步:将 kafka-eagle-bin-1.3.7.tar.gz 上传到服务器并解压
第四步:进入到 eagle的bin目录,给启动文件(ke.sh)执行权限
chmod 777 ke.sh
第五步:修改配置文件(eagle的conf目录下的 system-config.properties)
######################################
# multi zookeeper&kafka cluster list
######################################
kafka.eagle.zk.cluster.alias=cluster1
cluster1.zk.list=hadoop151:2181,hadoop152:2181,hadoop153:2181
######################################
# kafka offset storage
######################################
cluster1.kafka.eagle.offset.storage=kafka
######################################
# enable kafka metrics
######################################
kafka.eagle.metrics.charts=true
kafka.eagle.sql.fix.error=false
######################################
# kafka jdbc driver address
######################################
kafka.eagle.driver=com.mysql.jdbc.Driver
kafka.eagle.url=jdbc:mysql://hadoop151:3306/ke?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
kafka.eagle.username=root
kafka.eagle.password=123456
第六步:添加环境变量,并 source /etc/profile
# KE_HOME:kafka-eagle
export KE_HOME=/opt/software/eagle/kafka-eagle-web-1.3.7
export PATH=$PATH:$KE_HOME/bin
第七步:启动Zookeeper和Kafka
第八步:启动Eagle
bin/ke.sh start
第九步:登录页面查看监控数据(用户名和密码:启动Eagle时显示)
http://192.168.9.102:8048/ke
第一步:编写Flume配置文件(flume-kafka.conf)
#name
a1.sources = r1
a1.sinks = k1
a1.channels = c1
#source配置
a1.sources.r1.type = netcat
a1.sources.r1.bind = hadoop151
a1.sources.r1.port = 44444
#sink配置
a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
a1.sinks.k1.kafka.topic = fzk
a1.sinks.k1.kafka.bootstrap.servers = hadoop151:9092,hadoop152:9092,hadoop153:9092
a1.sinks.k1.kafka.flumeBatchSize = 20
a1.sinks.k1.kafka.producer.acks = 1
a1.sinks.k1.kafka.producer.linger.ms = 1
#channel配置
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
#source-channel-sink之间的联系
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
第二步:开启kafka消费者
bin/kafka-console-consumer.sh --bootstrap-server hadoop151:9092,hadoop152:9092,hadoop153:9092 \
--topic fzk
第三步:启动Flume
bin/flume-ng agent -n agent名称 -c conf/ -f flume-kafka.conf文件路径及文件名
#执行
bin/flume-ng agent -n a1 -c conf/ -f job/flume-kafka.conf