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写数据的原因有很多:用户行为分析.日志存储.异步通信等.多样化的使用场景带来了多样化的需求:消息是否能丢失?是 ...
随机推荐
- vue打包后dist的使用
发现问题 vue项目完成打包出dist后准备打开index.html,发现居然页面是一片空白,f12一片报红. 分析问题 经过多次网上查询后发现这是由于vue打包时,脚手架会帮你配置好大量参数,但其中 ...
- Redis 入门 - 图形化管理工具如何选择,最全分类
工欲善其事必先利其器,上一章Redis服务环境已经搭建完成,现在就需要一个趁手的工具,有个好工具可以做到事半功倍. Redis图形化管理工具五花八门,可供选择的很多,大家可以根据自己的需求应用场景进行 ...
- 小tips:怎样实现简单的前端hash与history路由方式?
前端路由实现方式,主要有两种,分别是history和hash模式. hash模式 不同路由对应的hash是不一样的,如何能够监听到URL中关于hash部分发生的变化?浏览器已经暴露给我们一个现成的方法 ...
- C语言位域的内存布局
本文将先粗略介绍大小端,和大小端的测试方法,最后介绍位域的内存布局. 1. 大小端 大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中. 小端模式,是指数据的高字节保存 ...
- [TK] Rudolf and Subway ( CodeForces #933 div.3 - G )
形式化题意 给定一个带权无向图,求从 \(s\) 点到 \(e\) 点的路径上途径边权种类的最小值. 思路 题图 我们把边权种类相同的点连成的子图抽象成一个 "平台" ,从题目给我 ...
- 国产OS 中标麒麟下 C# 桌面应用开发环境搭建笔记
1.中标麒麟 7.0 x86 桌面版 默认安装创建用户时,如果没勾选 root 用户使用相同的口令,那么安装完成以后,root 是没有设置口令的,通过 sudo passwd root 输入当前普通用 ...
- 多款国产操作系统安装数据库干货文档汇总(含Oracle/MySQL/国产数据库等)
随着国产化的逐步推进,越来越多的企业选择将数据库安装在国产操作系统上.为帮助大家了解国产操作系统上的数据库成功搭建案例与搭建方式,本文整理了墨天轮数据技术社区上用户分享的实操文档,涵盖银河麒麟.中标麒 ...
- 墨天轮专访TDengine陶建辉:坚持做难而正确的事,三次创业成就不悔人生
导读: 时序数据库(Time Series Database)在最近几年被越来越多的用户接受并使用,并有广泛的应用场景.云原生时序数据库 TDengine 一直稳居墨天轮时序数据库榜首,其近期的海外发 ...
- css实现直线拉伸
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 0606-nn.functional
0606-nn.functional 目录 一.nn.functional 和 nn.Module 的区别 二.nn.functional 和 nn.Module 结合使用 pytorch完整教程目录 ...