消息队列-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: 消费组使用的 再平衡协议 ,是一个枚举值,classic和consumer
  • topic: 主题

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

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、生产者确认机制

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

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

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

相关推荐
此时不提桶,更待何时12 小时前
06-23-A-RabbitMQ生态集成详解
分布式·rabbitmq
m0_6464299717 小时前
RabbitMQ 核心知识总结(生产实战版)
分布式·rabbitmq
DBA_G20 小时前
GBase 8c分布式数据库客户端工具 gsql
数据库·分布式
chunyublog20 小时前
Spark 词频统计练习
大数据·分布式·spark
ClouGence21 小时前
开源数据库管理工具 CloudDM 4.4.0 发布,新增 Kafka、SAP HANA 数据源
数据库·kafka
acrel721 小时前
高速公路分布式光伏并网电能质量与安全保护方案应用
分布式·安全
RobinXYuan21 小时前
【Kafka 源码手记】01 从消息队列到 Event Streaming
kafka·源码阅读
IT小小猪1 天前
# Hadoop 3.3.6 完全分布式集群部署知识库
hadoop·分布式·eclipse
此时不提桶,更待何时1 天前
06-24-B-RabbitMQ面试与生产事故实战
分布式·面试·rabbitmq
来福猿1 天前
分布式锁 Redis 实现源码分析:SETNX、过期时间与可重入设计
数据库·redis·分布式