Kafka API 三大API基本使用

1.简介

Kafka 有 5 个核心 API:

在GO sarama 中只展示了 

Kafka分为同步生产者和异步生产者,顾名思义,同步生产者每条消息都会实时发送到 Kafka,而异步生产者则为了提升性能,会等待存了一批消息或者到了指定间隔时间才会一次性发送到 Kafka。

2.Producer API

同步生产者的代码如下:

package main

import (
   "github.com/IBM/sarama"
   "kafka_project/conf"
   "log"
   "strconv"
)

// 本实例展示的同步生产者的使用
func main() {
   //生产10个消息
   Producer(10)
}

func Producer(limit int) {

   config := sarama.NewConfig()
   config.Producer.Return.Successes = true
   config.Producer.Return.Errors = true

   producer, err := sarama.NewSyncProducer([]string{conf.HOST}, config)
   if err != nil {
      log.Fatal("NewSyncProducer err:", err)
   }
   defer producer.Close()
   var success, errors int
   for i := 0; i < limit; i++ {
      str := "生产第" + strconv.Itoa(i) + "条消息"
      msg := &sarama.ProducerMessage{
         Topic: conf.TOPIC,
         Key:   nil,
         Value: sarama.StringEncoder(str)}
      partition, offset, err := producer.SendMessage(msg)
      if err != nil {
         log.Printf("SendMessage:%d err:%v\n ", i, err)
         errors++
         continue
      }
      success++
      log.Printf("[Producer] partitionid: %d; offset:%d, value: %s\n", partition, offset, str)
   }
   log.Printf("发送完毕 总发送条数:%d successes: %d errors: %d\n", limit, success, errors)
}

3.ConsumerAPI

package main

import (
   "github.com/IBM/sarama"
   "kafka_project/conf"
   "log"
)

func main() {
   //单分区消费
   SinglePartition()
}
func SinglePartition() {
   config := sarama.NewConfig()
   consumer, err := sarama.NewConsumer([]string{conf.HOST}, config)
   if err != nil {
      log.Fatal("NewConsumer err:", err)
   }
   defer consumer.Close()
   // 参数1 指定消费那个topic
   // 参数2 分区,这里默信0号分区
   // 参数3 offset 从哪儿开始消费起走,正常情况下每次消费完都会将这次的offset提交到kafka
   // 如果改为 sarama.OffsetOldest 则会从最旧的消息开始消费,即每次重启 consumer 都会把该 topic 下的所有消息消费一次
   partitionConsumer, err := consumer.ConsumePartition(conf.TOPIC, 0, sarama.OffsetOldest)
   if err != nil {
      log.Fatal("ConsumerParition err:", err)
   }
   defer partitionConsumer.Close()
   // 会一直阻塞在这里
   for message := range partitionConsumer.Messages() {
      log.Printf("[Consumer] partitionid: %d; offset:%d, value: %s\n", message.Partition, message.Offset, string(message.Value))
   }
}

运行测试:

启动生产端生产消息

启动消费端

反得启动消费端的话,发现消息会重复消费。

由于独立消费没有提交offset的功能,所以需要借助OffsetManager来完成

offsetManager的代码如下

package main

import (
   "fmt"
   "github.com/IBM/sarama"
   "kafka_project/conf"
   "log"
   "time"
)

func main() {
   OffsetManager()
}

func OffsetManager() {
   config := sarama.NewConfig()
   // 配置开启自动提交 offset,这样 samara 库会定时帮我们把最新的 offset 信息提交给 kafka
   config.Consumer.Offsets.AutoCommit.Enable = true              //开启自动提交
   config.Consumer.Offsets.AutoCommit.Interval = 1 * time.Second // 自动 commit时间间隔

   client, err := sarama.NewClient([]string{conf.HOST}, config)
   if err != nil {
      log.Fatal("NewClient err:", err)
   }
   defer client.Close()
   // offsetManager 用于管理每个 consumerGroup的 offset
   // 根据 groupID 来区分不同的 consumer,注意: 每次提交的 offset 信息也是和 groupID 关联的
   offsetManager, err := sarama.NewOffsetManagerFromClient("singleId", client)
   if err != nil {
      log.Println("NewOffsetManagerFromClient err:", err)
   }
   defer offsetManager.Close()
   // 每个分区的 offset 也是分别管理的,目前本机也只有一个分区topic 只有 1 个分区(这里面是指0分区)
   partitionOffsetManager, err := offsetManager.ManagePartition(conf.TOPIC, conf.TOPICPARTITION)
   if err != nil {
      log.Println("ManagePartition err:", err)
   }
   partitionOffsetManager.Close()
   //在程序结束后提交一次,防止消息丢失
   defer offsetManager.Commit()
   consumer, err := sarama.NewConsumerFromClient(client)
   if err != nil {
      log.Println("NewConsumerFromClient err:", err)
   }
   // 根据 kafka 中记录的上次消费的 offset 开始+1的位置接着消费
   nextOffset, _ := partitionOffsetManager.NextOffset() // 取得下一消息的偏移量作为本次消费的起点
   fmt.Println("nextOffset:", nextOffset)
   pc, err := consumer.ConsumePartition(conf.TOPIC, conf.TOPICPARTITION, nextOffset)
   if err != nil {
      log.Println("ConsumePartition err:", err)
   }
   defer pc.Close()

   for message := range pc.Messages() {
      value := string(message.Value)
      log.Printf("[Consumer] partitionid: %d; offset:%d, value: %s\n", message.Partition, message.Offset, value)
      // 每次消费后都更新一次 offset,这里更新的只是程序内存中的值,需要 commit 之后才能提交到 kafka
      // MarkOffset 更新最后消费的 offset
      partitionOffsetManager.MarkOffset(message.Offset+1, "modified metadata")
   }
}

运行offsetManager消费端反复消费,可以看到不会重复消费了

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值