消息队列-kafka的操作(三)

一、操作Kafka

1.1、安装librdkafka

git地址:https://github.com/confluentinc/librdkafka

shell 复制代码
git clone git@github.com:confluentinc/librdkafka.git

cd librdkafka
./configure

然后经典的编译安装

shell 复制代码
make
make install
ldconfig

注意: :安装后头文件位于 /usr/local/include/librdkafka/,库文件位于/usr/local/lib/

二、消费者程序分析

librdkafka/examples/下存在一些示例文件,先看下如何进行操作使用:

2.1、运行可执行程序

提示需要填入相关参数

shell 复制代码
# 先本地运行,端口默认为9092
./consumer localhost:9092 my-consumer-group-1 consumer test
  • broker:服务地址
  • group.id: 消费组编号
  • group.protocol: 消费组使用的 再平衡协议 ,是一个枚举值,classicconsumer
  • topic: 主题

**注意:**执行程序时,先确保zookeeperkafka服务已经启动

2.2、程序结构

参数解析

c 复制代码
// consumer.c
/*
* Argument validation
*/
if (argc < 4) {
    fprintf(stderr,
            "%% Usage: "
            "%s <broker> <group.id> <group.protocol> <topic1> "
            "<topic2>..\n",
            argv[0]);
        return 1;
    }

// 参数格式:<broker> <group.id> <group.protocol> <topic1> <topic2>..
brokers = argv[1];        // Kafka broker地址
groupid = argv[2];        // 消费者组ID
group_protocol = argv[3]; // 再平衡协议(classic/consumer)
topics = &argv[4];        // 要订阅的主题列表
topic_cnt = argc - 4;     // 主题数量

关键配置项

c 复制代码
// 1. 设置bootstrap servers
rd_kafka_conf_set(conf, "bootstrap.servers", brokers, ...);

// 2. 设置消费者组ID
rd_kafka_conf_set(conf, "group.id", groupid, ...);

// 3. 设置再平衡协议
rd_kafka_conf_set(conf, "group.protocol", group_protocol, ...);

// 4. 设置偏移量重置策略(earliest/latest)
rd_kafka_conf_set(conf, "auto.offset.reset", "earliest", ...);

消息处理循环

c 复制代码
while (run) {
    // 轮询消息,超时时间100ms
    rd_kafka_message_t *rkm = rd_kafka_consumer_poll(rk, 100);
    
    if (!rkm) continue;  // 超时,继续轮询
    
    if (rkm->err) {
        // 处理消费者错误
        fprintf(stderr, "%% Consumer error: %s\n",
                rd_kafka_message_errstr(rkm));
    } else {
        // 成功接收到消息
        printf("Message on %s [%d] at offset %lld\n",
               rd_kafka_topic_name(rkm->rkt),
               rkm->partition,
               rkm->offset);
        
        if (rkm->key) printf(" Key: %.*s\n", (int)rkm->key_len, (char*)rkm->key);
        if (rkm->payload) printf(" Value: %.*s\n", (int)rkm->len, (char*)rkm->payload);
    }
    
    rd_kafka_message_destroy(rkm);  // 释放消息资源
}

三、生产者程序分析

examples/目录下,存在两个生产者程序,一个是纯C,一个是CPP的,先看下C的

3.1、C程序特点

  1. 采用异步发送机制
    1. 使用rd_kafka_producev()异步发送消息
    2. 消息发送到内部队列后立即返回
    3. 通过回调函数获取发送结果
c 复制代码
retry:
    err = rd_kafka_producev(
    /* Producer handle */
        rk,
        /* Topic name */
        RD_KAFKA_V_TOPIC(topic),
        /* Make a copy of the payload. */
        RD_KAFKA_V_MSGFLAGS(RD_KAFKA_MSG_F_COPY),
        /* Message value and length */
        RD_KAFKA_V_VALUE(buf, len),
        /* Per-Message opaque, provided in
        * delivery report callback as
        * msg_opaque. */
        RD_KAFKA_V_OPAQUE(NULL),
        /* End sentinel */
        RD_KAFKA_V_END);

        if (err) {
            /*
            * Failed to *enqueue* message for producing.
            */
            fprintf(stderr,
                    "%% Failed to produce to topic %s: %s\n", topic,
                    rd_kafka_err2str(err));

                    if (err == RD_KAFKA_RESP_ERR__QUEUE_FULL) {
                                /* If the internal queue is full, wait for
                                 * messages to be delivered and then retry.
                                 * The internal queue represents both
                                 * messages to be sent and messages that have
                                 * been sent or failed, awaiting their
                                 * delivery report callback to be called.
                                 *
                                 * The internal queue is limited by the
                                 * configuration property
                                 * queue.buffering.max.messages and
                                 * queue.buffering.max.kbytes */
                        rd_kafka_poll(rk,
                            1000 /*block for max 1000ms*/);
                        goto retry;
                    }
                } else {
                        fprintf(stderr,
                                "%% Enqueued message (%zd bytes) "
                                "for topic %s\n",
                                len, topic);
                }
  1. 生产者数据流
text 复制代码
用户调用 producev()
        ↓
检查参数有效性
        ↓
尝试放入内部队列 ←─ 可能失败(队列满)
        ↓
成功入队 → 立即返回成功
        ↓
后台发送线程轮询队列
        ↓
批量发送到 Kafka Broker
        ↓
收到 Broker 响应
        ↓
调用 dr_msg_cb() 通知结果
  1. 消息状态机
text 复制代码
// 消息生命周期
MESSAGE_CREATED        // 消息创建
    ↓
ENQUEUED_SUCCESSFULLY  // 成功入队(producev() 返回成功)
    ↓
SENDING                // 后台线程正在发送
    ↓
SENT_SUCCESSFULLY      // 发送成功(dr_msg_cb 通知)
    OR
SENT_FAILED            // 发送失败(dr_msg_cb 通知)

3.2、C++程序特点

大体思路和C程序一致,只不过进行了类封装

c++ 复制代码
class ExampleDeliveryReportCb : public RdKafka::DeliveryReportCb {
 public:
  void dr_cb(RdKafka::Message &message) {
    /* If message.err() is non-zero the message delivery failed permanently
     * for the message. */
    if (message.err())
      std::cerr << "% Message delivery failed: " << message.errstr()
                << std::endl;
    else
      std::cerr << "% Message delivered to topic " << message.topic_name()
                << " [" << message.partition() << "] at offset "
                << message.offset() << std::endl;
  }
};

四、总结

4.1、消费者组与再平衡

  • 消费者组(Consumer Group):多个消费者实例可以组成一个组,共同消费一个或多个主题

  • 再平衡协议(Rebalance Protocol):当消费者加入或离开组时,如何重新分配分区

    • classic
    • consumer

4.2、偏移量管理

  • auto.offset.reset:当没有提交的偏移量时从哪里开始消费
    • earliest:从最早的消息开始
    • latest:从最新的消息开始
  • 消费者会自动定期提交偏移量

4.3、生产者确认机制

  • 异步发送:提高吞吐量,但需要处理发送结果

  • 队列缓冲:生产者内部有消息队列,可配置大小

  • 发送确认:通过回调函数或轮询获取发送结果

相关推荐
冷崖18 小时前
消息队列-kafka(一)
分布式·kafka
不光头强21 小时前
kafka学习要点
分布式·学习·kafka
编程彩机1 天前
互联网大厂Java面试:从分布式缓存到消息队列的技术场景解析
java·redis·面试·kafka·消息队列·微服务架构·分布式缓存
難釋懷1 天前
分布式锁-redission可重入锁原理
分布式
珠海西格1 天前
远动通信装置为何是电网安全运行的“神经中枢”?
大数据·服务器·网络·数据库·分布式·安全·区块链
CTO Plus技术服务中1 天前
分布式存储HBase开发与运维教程
运维·分布式·hbase
indexsunny1 天前
互联网大厂Java求职面试实战:Spring Boot微服务与Kafka消息队列应用解析
java·数据库·spring boot·微服务·面试·kafka·jpa
飞乐鸟1 天前
Github 16.8k Star!推荐一款开源的高性能分布式对象存储系统!
分布式·开源·github
panzer_maus1 天前
分布式锁的概念
分布式