生产者#
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
| 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.StringSerializer;
import java.util.Properties;
public class Producer {
public static void main(String[] args) {
Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.0.1:29092");
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
try (KafkaProducer<String, String> producer = new KafkaProducer<>(props)) {
String topic = "my-test-topic";
ProducerRecord<String, String> record = new ProducerRecord<>(topic, "key", "value");
// 异步发送消息
producer.send(record, (metadata, exception) -> {
if (exception == null) {
System.out.printf("Topic: %s, Partition: %d, Offset: %d%n",
metadata.topic(), metadata.partition(), metadata.offset());
} else {
exception.printStackTrace();
}
});
producer.flush();
}
}
}
|
消费者#
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
| import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;
import java.time.Duration;
import java.util.Collections;
import java.util.Properties;
public class Consumer {
public static void main(String[] args) {
Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.0.1:29092");
props.put(ConsumerConfig.GROUP_ID_CONFIG, "test-consumer-group");
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props)) {
consumer.subscribe(Collections.singletonList("my-test-topic"));
while (true) {
var messages = consumer.poll(Duration.ofMillis(100));
if (messages != null) {
for (var message : messages) {
System.out.println(message);
}
}
}
}
}
}
|
消费者组#
当需要将同一份完整的数据,同时交给完全不同的业务系统去独立处理时,就需要创建使用到消费者组。
场景举例:假设用户下了一笔订单,订单服务向 order-created-topic 发送了一条消息。下游有三个业务系统需要消费这条消息:
- 库存服务(Group A): 需要消费这条消息去扣减商品库存。
- 积分服务(Group B): 需要消费这条消息给用户增加会员积分。
- 通知服务(Group C): 需要消费这条消息给用户发送下单成功的短信。
为什么用多组:这三个服务是完全独立的业务逻辑。使用不同的组,Kafka 会把每一条订单消息完整地复制(广播)给这三个组,每个消费者组都有独立的 Offset,互不干扰。
Offset#
Rebalance#