golang之操作kafka
安装第三方包:
go get github.com/IBM/sarama
生产者实例:
package main import (
"fmt"
"github.com/IBM/sarama"
) func main() { //1.生产者配置
config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForAll //ACK,发送完数据需要leader和follow都确认
config.Producer.Partitioner = sarama.NewRandomPartitioner //分区,新选出一个分区
config.Producer.Return.Successes = true //确认,成功交付的消息将在success channel返回 //2.连接Kafka client, err := sarama.NewSyncProducer([]string{"127.0.0.1:9092"}, config)
if err != nil {
fmt.Println("Producer error", err)
return
} defer client.Close() //3.封装消息 msg := &sarama.ProducerMessage{}
msg.Topic = "log"
msg.Value = sarama.StringEncoder("this is test log") //4.发送消息
pid, offset, err := client.SendMessage(msg) if err != nil {
fmt.Println("send faild", err)
}
fmt.Printf("pid:%v offset:%v\n", pid, offset)
}
消费者:
package main import (
"fmt" // "github.com/Shopify/sarama" // 该包已经转移到了IBM/sarama
"github.com/IBM/sarama"
) // kafka consumer func main() {
consumer, err := sarama.NewConsumer([]string{"127.0.0.1:9092"}, nil)
if err != nil {
fmt.Printf("fail to start consumer, err:%v\n", err)
return
}
partitionList, err := consumer.Partitions("web_log") // 根据topic取到所有的分区
if err != nil {
fmt.Printf("fail to get list of partition:err%v\n", err)
return
}
fmt.Println(partitionList)
for partition := range partitionList { // 遍历所有的分区
// 针对每个分区创建一个对应的分区消费者
pc, err := consumer.ConsumePartition("web_log", int32(partition), sarama.OffsetNewest)
if err != nil {
fmt.Printf("failed to start consumer for partition %d,err:%v\n", partition, err)
return
}
defer pc.AsyncClose()
// 异步从每个分区消费信息
go func(sarama.PartitionConsumer) {
for msg := range pc.Messages() {
fmt.Printf("Partition:%d Offset:%d Key:%v Value:%v", msg.Partition, msg.Offset, msg.Key, msg.Value)
}
}(pc)
}
}
完整文件内容:
package main import (
"context"
"fmt"
"github.com/IBM/sarama"
"log"
"math"
"os"
"os/signal"
"sync"
"syscall"
) // 更多参考:https://kpretty.tech/archives/gokafkaclient var addrs = []string{"172.29.97.140:9092"}
var topic = "log" func producer() {
// 生产者配置
config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForAll // ACK
config.Producer.Partitioner = sarama.NewRandomPartitioner // 分区
// 异步回调(两个channel, 分别是成功和错误)
config.Producer.Return.Successes = true // 确认
config.Producer.Return.Errors = true sarama.Logger = log.New(os.Stdout, "[Sarama]", log.LstdFlags) // 连接kafka
// 同步
client, err := sarama.NewSyncProducer(addrs, config)
// 异步
//client, err := sarama.NewAsyncProducer(addrs, config)
if err != nil {
fmt.Println("producer error", err)
return
} defer func() {
_ = client.Close()
}() // 封装消息
msg := &sarama.ProducerMessage{
Topic: topic,
Value: sarama.StringEncoder("this is test log"),
} pid, offset, err := client.SendMessage(msg)
if err != nil {
fmt.Println("send failed", err)
return
} fmt.Printf("pid:%v offset:%v \n", pid, offset)
} func consumer() {
consumer, err := sarama.NewConsumer(addrs, nil)
if err != nil {
fmt.Printf("fail to start consumer, err:%v \n", err)
return
}
partitionList, err := consumer.Partitions(topic) // 通过topic获取所有分区
if err != nil {
fmt.Printf("fail to get partition list, err:%v\n", err)
return
} fmt.Println(partitionList)
for partition := range partitionList { // 遍历所有分区
pc, err := consumer.ConsumePartition(topic, int32(partition), sarama.OffsetNewest)
if err != nil {
fmt.Printf("failed to start consumer for partition %d, err:%v\n", partition, err)
return
}
defer pc.AsyncClose()
go func(sarama.PartitionConsumer) {
for msg := range pc.Messages() {
// 当设置了key的时候,不为空
fmt.Printf("Partition:%d Offset:%d Key:%s Value:%s\n", msg.Partition, msg.Offset, string(msg.Key), string(msg.Value))
}
}(pc)
}
//time.Sleep(5 * time.Second)
select {}
} func groupConsumer() {
groupId := "sarama-consumer"
config := sarama.NewConfig()
// 关闭自动提交 和 初始化策略(oldest|newest)
config.Consumer.Offsets.AutoCommit.Enable = false
config.Consumer.Offsets.Initial = sarama.OffsetOldest
sarama.NewConsumerGroup(addrs, groupId, config)
} func main() {
// 生产者
//producer()
// 消费者(只能连续读取,中断期间会丢失数据)
//consumer() // 消费者
//groupConsumer()
SimpleConsumer()
} var groupID = "sarama-consumer"
var asyncOffset chan struct{}
var wg sync.WaitGroup const defaultOffsetChannelSize = math.MaxInt func SimpleConsumer() {
brokers := addrs
// 消费者配置
config := sarama.NewConfig()
// 关闭自动提交
config.Consumer.Offsets.AutoCommit.Enable = false
config.Consumer.Offsets.Initial = sarama.OffsetOldest
// 开启日志
logger := log.New(os.Stdout, "[Sarama] ", log.LstdFlags)
sarama.Logger = logger
consumer, err := sarama.NewConsumerGroup(brokers, groupID, config)
if err != nil {
panic(err)
}
defer func() { _ = consumer.Close() }()
// 搞一个上下文用于终止消费者
ctx, cancelFunc := context.WithCancel(context.Background())
// 监听终止信号
go func() {
logger.Println("monitor signal")
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
<-quit
logger.Println("stop consumer")
cancelFunc()
}()
// 消费数据
err = consumer.Consume(ctx, []string{topic}, &Consumer{})
if err != nil {
panic(err)
}
// 等待所有偏移量都提交完毕再退出
logger.Println("当前存在未提交的偏移量")
wg.Wait()
} type Consumer struct{} func (c *Consumer) Setup(session sarama.ConsumerGroupSession) error {
// 初始化异步提交的channel
asyncOffset = make(chan struct{}, defaultOffsetChannelSize)
wg.Add(1)
// 异步提交偏移量
go func() {
for range asyncOffset {
session.Commit()
}
wg.Done()
}()
return nil
} func (c *Consumer) Cleanup(_ sarama.ConsumerGroupSession) error {
// 关闭通道
close(asyncOffset)
return nil
} func (c *Consumer) ConsumeClaim(session sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error {
EXIT:
for {
select {
case message := <-claim.Messages():
log.Printf("Message claimed: key= %s, value = %s, timestamp = %v, topic = %s", string(message.Key), string(message.Value), message.Timestamp, message.Topic)
// 标记消息,并不是提交偏移量
session.MarkMessage(message, "")
// 异步提交
asyncOffset <- struct{}{}
case <-session.Context().Done():
log.Println("cancel consumer")
break EXIT
}
}
return nil
}
更深入使用:
golang之操作kafka的更多相关文章
- Golang中如何正确的使用sarama包操作Kafka?
Golang中如何正确的使用sarama包操作Kafka? 一.背景 在一些业务系统中,模块之间通过引入Kafka解藕,拿IM举例(图来源): 用户A给B发送消息,msg_gateway收到消息后,投 ...
- Java操作Kafka
java操作kafka非常的简单,然后kafka也提供了很多缺省值,一般情况下我们不需要修改太多的参数就能使用.下面我贴出代码. pom.xml <dependency> <grou ...
- SparkStreaming操作Kafka
Kafka为一个分布式的消息队列,spark流操作kafka有两种方式: 一种是利用接收器(receiver)和kafaka的高层API实现. 一种是不利用接收器,直接用kafka底层的API来实现( ...
- kfka学习笔记一:使用Python操作Kafka
1.准备工作 使用python操作kafka目前比较常用的库是kafka-python库,但是在安装这个库的时候需要依赖setuptools库和six库,下面就要分别来下载这几个库 https://p ...
- Java操作Kafka执行不成功
使用kafka-clients操作kafka始终不成功,原因不清楚,下面贴出相关代码及配置,请懂得指点一下,谢谢! 环境及依赖 <dependency> <groupId>or ...
- go语言操作kafka
go语言操作kafka Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据,具有高性能.持久化.多副本备份.横向扩展等特点.本文介绍了如何使用Go语言发送和 ...
- 使用python操作kafka
使用python操作kafka目前比较常用的库是kafka-python库 安装kafka-python pip3 install kafka-python 生产者 producer_test.py ...
- C++操作Kafka使用Protobuf进行跨语言数据交互
C++操作Kafka使用Protobuf进行跨语言数据交互 Kafka 是一种分布式的,基于发布 / 订阅的消息系统.主要设计目标如下: 以时间复杂度为 O(1) 的方式提供消息持久化能力,即使对 T ...
- GO学习-(30) Go语言操作kafka
go操作kafka Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据,具有高性能.持久化.多副本备份.横向扩展等特点.本文介绍了如何使用Go语言发送和接收 ...
- kafka实战教程(python操作kafka),kafka配置文件详解
kafka实战教程(python操作kafka),kafka配置文件详解 应用往Kafka写数据的原因有很多:用户行为分析.日志存储.异步通信等.多样化的使用场景带来了多样化的需求:消息是否能丢失?是 ...
随机推荐
- 【YashanDB数据库】YashanDB如何回收表空间
确认表空间高水位线,是否有可回收空间. select a.tablespace_name,a.high_water_mark,b.user_bytes,b.total_bytes from (SELE ...
- C#整合Ollama实现本地LLMs调用
前言 近两年AIGC发展的非常迅速,从刚开始的只有ChatGPT到现在的很百家争鸣.从开始的大参数模型,再到后来的小参数模型,从一开始单一的文本模型到现在的多模态模型等等.随着一起进步的不仅仅是模型的 ...
- sql 查询死锁
1 -- 查询死锁 2 --第一种 3 sp_lock 4 5 --第二种 6 select object_name(resource_associated_entity_id) as tableNa ...
- 小tips:nodejs请求接口超时使用中间件connect-timeout实现自动超时机制
如果在请求中不设置超时时间,那么一直处理loading卡屏状态,使用connect-timeout来设置自动超时时间. 安装: npm install connect-timeout -S 如下例子: ...
- 使用vue-cli4快速搭建项目环境、使用webpack4打包自己的library类库、封装vue插件并发布
快速创建 使用官方推荐的vue-cli创建项目如下: # 安装 Vue Cli npm install -g @vue/cli # 创建一个项目 vue create vanttest # 创建完成后 ...
- web前端使用mcg-helper代码生成工具学习笔记
学习资料介绍 github地址:mcg-helper代码生成工具 什么是 FreeMarker? - FreeMarker 中文官方参考手册 视频学习地址: 第一节.视频教程内容介绍 探讨研发工作 ...
- CCIA数安委等组织发起“个人信息保护影响评估专题工作”,合合信息首批入选试点
近期,"个人信息保护影响评估专题工作"(简称"PIA专题工作")试点评估结果正式发布.PIA专题工作组由中国电子技术标准化研究院.中国信息通信院等单位的法律与技 ...
- 【赵渝强老师】Kafka的持久化
一.Kafka持久化概述 Kakfa 依赖文件系统来存储和缓存消息.对于硬盘的传统观念是硬盘总是很慢,基于文件系统的架构能否提供优异的性能?实际上硬盘的快慢完全取决于使用方式.同时 Kafka 基于 ...
- Java日期时间API系列26-----Jdk8中java.time包中的新的日期时间API类,YearMonth类的源码,转换和应用。
Java8中为年月新增了类YearMonth,可以用来表示卡片过期时间等问题. 1.YearMonth 默认格式为:2007-12 1.1 部分源码 * * @implSpec * This clas ...
- 使用 OpenFunction 在任何基础设施上运行 Serverless 工作负载
作者: 霍秉杰:KubeSphere 可观测性.边缘计算和 Serverless 团队负责人,Fluent Operator 和 OpenFunction 项目的创始人,还是多个可观测性开源项目包括 ...