Java使用Kafka示例

pom.xml

1
2
3
4
5
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>3.4.0</version>
</dependency>

java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package cn.idea360.assistant.dev.kafka;

import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;

import java.time.Duration;
import java.util.Collections;
import java.util.Properties;

/**
* @author cuishiying
* @date 2023-06-20
*/
@Slf4j
public class SimpleKafkaClient {

public SimpleKafkaClient() {
}

public static KafkaProducer<String, String> createProducer() {
// System.out.println("ProducerConfig默认配置: " + ProducerConfig.configDef().defaultValues());
Properties props = new Properties();
// Kafka 集群的地址
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "10.10.10.205:9092");
// 用于序列化键的类
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
// 用于序列化值的类
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
// 指定 producer 需要从 leader 收到多少个确认消息才认为消息发送成功("all": 最高保障,所有 ISR 都确认, "1": 仅 leader 确认, "0": 不等待确认)
props.put(ProducerConfig.ACKS_CONFIG, "all");
// 发送失败时,producer 重试的次数
props.put(ProducerConfig.RETRIES_CONFIG, 3);
// producer 批量发送消息的大小(单位:字节 (bytes) 16KB)
props.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
// 等待时间,以便收集更多消息批量发送(单位:毫秒 (ms))
props.put(ProducerConfig.LINGER_MS_CONFIG, 1);
// producer 用于缓冲的总内存大小(单位:字节 (bytes) 32MB)
props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 33554432);
// producer 发送消息阻塞的最长时间(单位:毫秒 (ms))
props.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, 60000);
// 压缩类型,如 "gzip", "snappy"
props.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "gzip");
// 是否启用幂等性,确保消息不会重复发送
props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true);

return new KafkaProducer<>(props);
}

public static KafkaConsumer<String, String> createConsumer() {
// System.out.println("ConsumerConfig默认配置: " + ConsumerConfig.configDef().defaultValues());
Properties props = new Properties();
// Kafka 集群的地址
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "10.10.10.205:9092");
// 消费者所属的组 ID
props.put(ConsumerConfig.GROUP_ID_CONFIG, "your-consumer-group");
// 用于反序列化键的类
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
// 用于反序列化值的类
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
// 指定没有初始偏移量时该怎么办("earliest": 从最早的偏移量开始, "latest": 从最新的偏移量开始)
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
// 是否自动提交偏移量
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
// Consumer 与 Kafka broker 之间 session 过期的时间(单位:毫秒 (ms))
props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, 10000);
// 每次调用 poll() 方法时返回的最大记录数
props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 500);
// Consumer 在等待响应之前,broker 必须提供的最小数据量(单位:字节 (bytes))
props.put(ConsumerConfig.FETCH_MIN_BYTES_CONFIG, 1);
// Consumer 在发出 fetch 请求后等待 broker 响应的最长时间(单位:毫秒 (ms))
props.put(ConsumerConfig.FETCH_MAX_WAIT_MS_CONFIG, 500);
// Consumer 向 Kafka broker 发送心跳的间隔时间(单位:毫秒 (ms))
props.put(ConsumerConfig.HEARTBEAT_INTERVAL_MS_CONFIG, 3000);

return new KafkaConsumer<>(props);
}

public static void main(String[] args) {
String topic = "test_data";
String key = "key";
String value = "idea360.cn";
// 生产消息
KafkaProducer<String, String> producer = CustomKafkaClient.createProducer();
ProducerRecord<String, String> producerRecord = new ProducerRecord<>(topic, key, value);
producer.send(producerRecord, (metadata, exception) -> {
if (exception == null) {
System.out.printf("Sent record [%s] with key [%s] to partition [%s] with offset [%s]%n", value, key, metadata.partition(), metadata.offset());
} else {
exception.printStackTrace();
}
});
producer.close();

// 消费消息
KafkaConsumer<String, String> consumer = CustomKafkaClient.createConsumer();
consumer.subscribe(Collections.singletonList(topic));
try {
while (true) {
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
for (ConsumerRecord<String, String> record : records) {
System.out.printf("Consumed record with key [%s] and value [%s] from partition [%d] with offset [%d]%n",
record.key(), record.value(), record.partition(), record.offset());
}
consumer.commitSync();
}
} finally {
consumer.close();
}
}
}