kafka独立消费者案例(订阅主题)

好的,这是一个使用 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();
        }
    }
}

关键点解释:

  1. group.id = null 这是声明独立消费者的关键配置项。它告诉 Kafka 这个消费者不属于任何组,不会参与消费者组的再平衡机制。
  2. assign() vs subscribe() 独立消费者必须使用 assign() 方法显式地指定要消费的 TopicPartition 列表。不能使用 subscribe() 方法(subscribe() 是用于加入消费者组并让 Kafka 自动分配分区的)。
  3. 分区选择: 你需要自己决定消费哪些分区。示例中消费了分区 0 (new TopicPartition(topicName, 0))。你可以消费单个分区、多个分区,甚至整个主题的所有分区(需要获取分区信息并全部分配)。对于独立消费者,一个常见的场景是每个消费者实例专门处理某个特定分区。
  4. 偏移量管理:
    • auto.offset.reset:决定了当消费者第一次启动或没有有效的偏移量记录时从哪里开始消费(earliest 最早消息,latest 最新消息)。
    • enable.auto.commit = false:通常设置为 false,意味着消费者不会自动提交消费过的消息偏移量。这让你可以精确控制在处理完消息后再提交偏移量,避免消息丢失(如果处理失败,可以重新消费)。
    • 在示例中,提交偏移量的代码 (consumer.commitSync()commitAsync()) 被注释掉了。在实际应用中,你需要在成功处理完一批消息后手动提交偏移量。
  5. 拉取循环 (poll): 消费者通过 poll(Duration) 方法从 Kafka 拉取消息。Duration 参数指定了拉取请求的超时时间(如果没有消息到达)。

使用场景:

  • 需要精确控制分区分配(例如,将特定分区固定分配给特定消费者实例)。
  • 需要消费历史数据(从特定偏移量开始)。
  • 消费者实例数量与主题分区数量相同,且希望每个消费者独占一个分区。
  • 不适合使用消费者组协调机制的场景。

注意事项:

  • 独立消费者不会触发消费者组的再平衡(Rebalance)。
  • 如果分区数量发生变化(增加或减少),独立消费者不会自动感知,需要你的应用程序逻辑来处理这种情况。
  • 手动管理分区分配和偏移量提交增加了复杂性,但也提供了更高的控制力。确保正确处理偏移量提交以避免重复消费或消息丢失。
相关推荐
刘一说18 分钟前
Spring Cloud微服务中的分布式追踪:从故障定位到性能优化的革命性实践
分布式·spring cloud·微服务
码农水水3 小时前
中国电网Java面试被问:流批一体架构的实现和状态管理
java·c语言·开发语言·面试·职场和发展·架构·kafka
程序员agions3 小时前
Node.js 爬虫实战指南(三):分布式爬虫架构,让你的爬虫飞起来
分布式·爬虫·node.js
回家路上绕了弯5 小时前
Spring Boot多数据源配置实战指南:从选型到落地优化
分布式·后端
小雨下雨的雨6 小时前
Flutter鸿蒙共赢——生命之痕:图灵图样与反应-扩散方程的生成美学
分布式·flutter·华为·交互·harmonyos·鸿蒙系统
用户2190326527357 小时前
SpringCloud分布式追踪深度实战:Sleuth+Zipkin从入门到生产部署全攻略
分布式·后端·spring cloud
Knight_AL7 小时前
深入理解 RabbitMQ 的AMQP 交换机类型与路由机制
分布式·rabbitmq
lang201509288 小时前
Java高性能缓存库Caffeine全解析
java·缓存·linq
是垚不是土8 小时前
单节点部署 Kafka Kraft 集群
分布式·kafka