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?
问题现象 在各个项目实施中,我们经常遇到客户.开发人员需要连接和使用YashanDB但不知如何操作的问题,本文旨在介绍远程连接.使用YashanDB的几种方式. 问题的风险及影响 无风险 问题影响的版 ...
- 【YashanDB知识库】表收集统计信息默认阈值引起SQL执行效率差
[问题分类]性能优化 [关键字]统计信息,阈值,执行计划 [问题描述]表新增87w数据自动收集统计信息任务没有启动导致SQL执行计划变差 [问题原因分析] CUS_REGISTER_READ 数据总量 ...
- 【YashanDB知识库】YAS-00220, utf8 sequence is wrong
[问题分类]功能使用 [关键字]YAS-00220,utf8 sequence is wrong [问题描述]在数据库执行select语句时,或者在exp导出数据库用户时报这个错误,表字段中同时存在n ...
- Windbg常用命令及分析套路
自己也在使用windbg分析问题,但是属于刚入门所以转发下大神的总结:https://www.cnblogs.com/fj365/p/13295453.html 常用 !threadpool 查看线程 ...
- 【学习笔记】数位DP
数位DP 适用条件 此类题目一般要求在\([l,r]\)区间内满足条件的数的个数,答案一般与数的大小无关,而与数各位的组成有关.题目中给出的数的范围一般较大,往往在\(10^9\)以上因此无法暴力枚举 ...
- [Tkey] OSU!
更新的题解可看 此处 你说得对但是 恐怖日本病毒会自动向你的电脑中下载 OSU! 题意简述 一个 01 串,每个位置有 \(p_{i}\) 的概率为 \(1\),连续的 \(x\) 个 \(1\) 贡 ...
- 前端使用 Konva 实现可视化设计器(23)- 绘制曲线、属性面板
本章分享一下如何使用 Konva 绘制基础图形:曲线,以及属性面板的基本实现思路,希望大家继续关注和支持哈(多求 5 个 Stars 谢谢)! 请大家动动小手,给我一个免费的 Star 吧~ 大家如果 ...
- MySQL事务理论及实现
理论大多引自<高性能MySQL>一书,不过在自测的过程中不知道是不是SQL版本的问题,还是操作有问题,在设置事务隔离级别的时候 按书上讲SET TRANSACTION ISOLATION ...
- Nodejs C++插件(N-API)
Nodejs C++插件(N-API) 0. 环境搭建 1. JS中调用C++方法 1.1 JS中调用源文件的C++方法 1.2 JS中调用动态库的C++方法 2. C++中调用JS方法 2.1. C ...
- Windows10 安装使用 Docker
Windows10 安装使用 Docker 下载安装 Docker Desktop https://docs.docker.com/docker-for-windows/install/ 点击运行 D ...