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写数据的原因有很多:用户行为分析.日志存储.异步通信等.多样化的使用场景带来了多样化的需求:消息是否能丢失?是 ...
随机推荐
- 探索不同引擎Innodb和Myisam的索引优化方案
数据库可能存在千万级的数据,必须将这些行数据以一定的结构组织起来做到高效的增删改查. 我们将分别探索innodb和myisam两种引擎的索引方案. 一.InnoDB的索引 1.假设表初始没有记录,只有 ...
- 超轻量级、支持插件的 .NET 网络通信框架
前言 给大家推荐一个轻量级的.支持插件的综合网络通信库:TouchSocket. TouchSocket 的基础通信功能包括 TCP.UDP.SSL.RPC 和 HTTP.其中,HTTP 服务器支持 ...
- 【LLM训练系列】从零开始训练大模型之Phi2-mini-Chinese项目解读
一.前言 本文主要是在复现和实践Phi2-mini-Chinese后,简要分析下Phi2-mini-Chinese这个项目,做一个学习实战总结. 原文发布于知乎:https://zhuanlan.zh ...
- 如何使用ChatGPT自带插件
OpenAI的插件将ChatGPT连接到第三方应用程序.这些插件使ChatGPT能够与开发者定义的API进行交互,增强ChatGPT的能力,并使其能够执行广泛的操作.插件使ChatGPT能够做如下事情 ...
- fluent python-chap3-1
class collections.OrderedDict([items]) 返回一个 dict 子类的实例,它具有专门用于重新排列字典顺序的方法. """ move_t ...
- C# .net 6 Log4net 安装、配置 以及相关问题处理
安装log4net 首先下载相关Nuget包 安装的时候注意项目的.net版本,我这里使用的是.net 6 在根目录下面新建一个配置文件 log4net.config,并且添加下面相关配置项目 < ...
- Angular Material 18+ 高级教程 – Datepicker の Calendar & Custom DateAdapter (Temporal)
前言 本篇只会教 Angular Material Datepicker 里最关键的组件 -- Calendar 组件. 还有如何自定义 DateAdapter,让 Calendar 支持 TC39 ...
- TypeScript – tsconfig
前言 上一篇 TypeScript – Get Started 使用了命令 tsc index.ts --module es2015 很少人会在命令时给写 config, 更正规的做法是创建一个 ts ...
- DQL—查询操作
一.查询语法 select 字段列表 from 表名列表 where 条件列表 group by 分组列表 having 分组后条件 order by 排序字段 limit 分页限定 (提供一个表来操 ...
- Kubernetes集群证书过期解决办法
问题现象 K8S集群证书过期后,会导无法创建Pod,通过kubectl get nodes也无法获取信息,甚至dashboard也无法访问. 一.确认K8S证书过期时间 查看k8s某一证书过期时间: ...