好的,这是一个使用 Kafka 独立消费者订阅主题并消费消息的基本案例(使用 Java 语言):
1)需求:
创建一个独立消费者,消费 first 主题中数据。
注意: 在消费者 API 代码中必须配置消费者组 id。命令行启动消费者不填写消费者组 id 会被自动填写随机的消费者组 id。

核心概念:
- 独立消费者: 指的是一个消费者实例不加入任何消费者组 (
group.id设置为null)。它独立地订阅主题分区并消费消息,不受其他消费者实例的影响。 - 订阅主题: 消费者指定一个或多个 Kafka 主题来消费消息。
- 手动分配分区: 独立消费者需要自己决定消费哪些分区(通常是通过
assign方法手动分配),而不是依赖 Kafka 的消费者组协调机制来自动分配。
代码示例:
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.common.TopicPartition;
import java.time.Duration;
import java.util.Collections;
import java.util.Properties;
public class StandaloneConsumerExample {
public static void main(String[] args) {
// 1. 配置消费者属性
Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); // Kafka 集群地址
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
props.put(ConsumerConfig.GROUP_ID_CONFIG, null); // 关键:设置为 null 表示独立消费者
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); // 如果没有有效偏移量,从最早的消息开始
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false"); // 通常手动提交偏移量以控制可靠性
// 2. 创建 Kafka 消费者实例
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
// 3. 指定要订阅的主题
String topicName = "your_target_topic"; // 替换为你的主题名
TopicPartition partitionToConsume = new TopicPartition(topicName, 0); // 示例:消费分区 0
// 如果需要消费多个分区:
// List<TopicPartition> partitions = Arrays.asList(
// new TopicPartition(topicName, 0),
// new TopicPartition(topicName, 1)
// );
// 4. 手动分配分区(核心步骤)
consumer.assign(Collections.singletonList(partitionToConsume)); // 分配单个分区
// consumer.assign(partitions); // 分配多个分区
try {
// 5. 轮询消息
while (true) {
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100)); // 拉取消息
for (ConsumerRecord<String, String> record : records) {
// 6. 处理接收到的消息
System.out.printf("Received message: topic = %s, partition = %d, offset = %d, key = %s, value = %s%n",
record.topic(), record.partition(), record.offset(), record.key(), record.value());
// 业务逻辑处理...
}
// 7. 手动提交偏移量 (可选,但推荐用于可靠性)
// consumer.commitSync(); // 同步提交
// 或 consumer.commitAsync(); // 异步提交
}
} finally {
// 8. 关闭消费者
consumer.close();
}
}
}
关键点解释:
group.id = null: 这是声明独立消费者的关键配置项。它告诉 Kafka 这个消费者不属于任何组,不会参与消费者组的再平衡机制。assign()vssubscribe(): 独立消费者必须使用assign()方法显式地指定要消费的TopicPartition列表。不能使用subscribe()方法(subscribe()是用于加入消费者组并让 Kafka 自动分配分区的)。- 分区选择: 你需要自己决定消费哪些分区。示例中消费了分区 0 (
new TopicPartition(topicName, 0))。你可以消费单个分区、多个分区,甚至整个主题的所有分区(需要获取分区信息并全部分配)。对于独立消费者,一个常见的场景是每个消费者实例专门处理某个特定分区。 - 偏移量管理:
auto.offset.reset:决定了当消费者第一次启动或没有有效的偏移量记录时从哪里开始消费(earliest最早消息,latest最新消息)。enable.auto.commit = false:通常设置为false,意味着消费者不会自动提交消费过的消息偏移量。这让你可以精确控制在处理完消息后再提交偏移量,避免消息丢失(如果处理失败,可以重新消费)。- 在示例中,提交偏移量的代码 (
consumer.commitSync()或commitAsync()) 被注释掉了。在实际应用中,你需要在成功处理完一批消息后手动提交偏移量。
- 拉取循环 (
poll): 消费者通过poll(Duration)方法从 Kafka 拉取消息。Duration参数指定了拉取请求的超时时间(如果没有消息到达)。
使用场景:
- 需要精确控制分区分配(例如,将特定分区固定分配给特定消费者实例)。
- 需要消费历史数据(从特定偏移量开始)。
- 消费者实例数量与主题分区数量相同,且希望每个消费者独占一个分区。
- 不适合使用消费者组协调机制的场景。
注意事项:
- 独立消费者不会触发消费者组的再平衡(
Rebalance)。 - 如果分区数量发生变化(增加或减少),独立消费者不会自动感知,需要你的应用程序逻辑来处理这种情况。
- 手动管理分区分配和偏移量提交增加了复杂性,但也提供了更高的控制力。确保正确处理偏移量提交以避免重复消费或消息丢失。