工作中需要将原先的消息队列替换成kafka,于是接触了基于go实现的sarama,又因为sarama不支持consumer group,于是又使用了sarama cluster,同时又希望尽量保证消费一次的语义,说到这个exactly once,sarama从去年就立了issue要支持exactly once,结果到现在还没支持(https://github.com/Shopify/sarama/issues/901)。
于是就自己造了个简单的轮子,把sarama和sarama cluster封装到一起,同时实现了保证消费一次的语义,我给它起名为kago。
先附上kago的依赖,需要先进行安装:
go get github.com/Shopify/sarama
go get github.com/bsm/sarama-cluster
然后便可以安装kago:
go get go get github.com/JeffreyDing11223/kago
先看一下kago的代码结构:
asyncProducer.go
负责初始化异步producer单个实例或实例group,以及发送消息,接受错误信息等。
syncProducer.go
负责初始化同步producer单个实例或实例group,同步发送消息等。
consumer.go
负责初始化consumer group单个成员或多个成员,以及初始化partition consumer,还有标记offset,提交offset,获取所有topics,以及获取某个topic下所有分区等等。
message.go
各类消息体的定义,基本都沿用了sarama和sarama cluster的消息类型。
offsetFile.go
初始化,修改,保存offset文件的相关操作。
offsetManager.go
offsetManager的初始化,标记offset等,这个主要结合partition consumer来使用。
config.go
kafka 生产者和消费者以及其他的各项配置。
util.go
各类功能函数。
这里有小伙伴一定有疑问了,既然已经有标记offset和提交offset了,为什么还要offsetFile.go
去操作文件来保存offset呢,这就是我上面说的尽可能保证消费一次的语义,试想一下,现在我拿到一条消息,各种加工处理,消费完了,当我要提交offset给kafka的时候,我的客户端出现网络问题了或者kafka server出了问题,导致offset提交失败。也就是说,下次继续消费的时候,就会继续从这条消息开始消费,那就相当于是重复消费了这条消息。于是我在处理消息和提交offset的中间,加了一步,就是文件保存offset,并且供使用者自己选择,继续消费是按照kafka server保存的offset来,还是按照本地文件来,或者取两者最大的,这些选项可以在config.go
中看到。