本文主要研究一下golang的zap的ZapKafkaWriter
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:域名與空間、虛擬空間、營銷軟件、網站建設、黃岡網站維護、網站推廣。
WriteSyncer內嵌了io.Writer接口,定義了Sync方法;Sink接口內嵌了zapcore.WriteSyncer及io.Closer接口;ZapKafkaWriter實現(xiàn)Sink接口及zapcore.WriteSyncer接口,其Write方法直接將data通過kafka發(fā)送出去。
最近寫了個kafka的接收消息的功能,需要使用回調處理收到的消息。
一個是基本的回調,一個是使用接口功能實現(xiàn)回調,對接口是個很好的學習。
1.正?;卣{
kafka的接收消息處。收到消息后,使用傳入的Onmessage進行處理。
調用kafka接收消息的單元,并在調用方寫好回調
在調用方實現(xiàn)回調需要執(zhí)行的方法
感覺還是使用基本回調相對簡單點,接口就當學習了。
另外跨包的接口的方法要大寫!定位了好久發(fā)現(xiàn)個入門的問題。
一、Kafka簡述
1. 為什么需要用到消息隊列
異步:對比以前的串行同步方式來說,可以在同一時間做更多的事情,提高效率;
解耦:在耦合太高的場景,多個任務要對同一個數(shù)據(jù)進行操作消費的時候,會導致一個任務的處理因為另一個任務對數(shù)據(jù)的操作變得及其復雜。
緩沖:當遇到突發(fā)大流量的時候,消息隊列可以先把所有消息有序保存起來,避免直接作用于系統(tǒng)主體,系統(tǒng)主題始終以一個平穩(wěn)的速率去消費這些消息。
2.為什么選擇kafka呢?
這沒有絕對的好壞,看個人需求來選擇,我這里就抄了一段他人總結的的優(yōu)缺點,可見原文
kafka的優(yōu)點:
1.支持多個生產者和消費者2.支持broker的橫向拓展3.副本集機制,實現(xiàn)數(shù)據(jù)冗余,保證數(shù)據(jù)不丟失4.通過topic將數(shù)據(jù)進行分類5.通過分批發(fā)送壓縮數(shù)據(jù)的方式,減少數(shù)據(jù)傳輸開銷,提高吞高量6.支持多種模式的消息7.基于磁盤實現(xiàn)數(shù)據(jù)的持久化8.高性能的處理信息,在大數(shù)據(jù)的情況下,可以保證亞秒級的消息延遲9.一個消費者可以支持多種topic的消息10.對CPU和內存的消耗比較小11.對網絡開銷也比較小12.支持跨數(shù)據(jù)中心的數(shù)據(jù)復制13.支持鏡像集群
kafka的缺點:
1.由于是批量發(fā)送,所以數(shù)據(jù)達不到真正的實時2.對于mqtt協(xié)議不支持3.不支持物聯(lián)網傳感數(shù)據(jù)直接接入4.只能支持統(tǒng)一分區(qū)內消息有序,無法實現(xiàn)全局消息有序5.監(jiān)控不完善,需要安裝插件6.需要配合zookeeper進行元數(shù)據(jù)管理7.會丟失數(shù)據(jù),并且不支持事務8.可能會重復消費數(shù)據(jù),消息會亂序,可用保證一個固定的partition內部的消息是有序的,但是一個topic有多個partition的話,就不能保證有序了,需要zookeeper的支持,topic一般需要人工創(chuàng)建,部署和維護一般都比mq高
3. Golang 操作kafka
3.1. kafka的環(huán)境
網上有很多搭建kafka環(huán)境教程,這里就不再搭建,就展示一下kafka的環(huán)境,在kubernetes上進行的搭建,有需要的私我,可以發(fā)yaml文件
3.2. 第三方庫
github.com/Shopify/sarama // kafka主要的庫*github.com/bsm/sarama-cluster // kafka消費組
3.3. 消費者
單個消費者
funcconsumer(){varwg sync.WaitGroup? consumer, err := sarama.NewConsumer([]string{"172.20.3.13:30901"},nil)iferr !=nil{? ? ? fmt.Println("Failed to start consumer: %s", err)return}? partitionList, err := consumer.Partitions("test0")//獲得該topic所有的分區(qū)iferr !=nil{? ? ? fmt.Println("Failed to get the list of partition:, ", err)return}forpartition :=rangepartitionList {? ? ? pc, err := consumer.ConsumePartition("test0",int32(partition), sarama.OffsetNewest)iferr !=nil{? ? ? ? fmt.Println("Failed to start consumer for partition %d: %s\n", partition, err)return}? ? ? wg.Add(1)gofunc(sarama.PartitionConsumer){//為每個分區(qū)開一個go協(xié)程去取值formsg :=rangepc.Messages() {//阻塞直到有值發(fā)送過來,然后再繼續(xù)等待fmt.Printf("Partition:%d, Offset:%d, key:%s, value:%s\n", msg.Partition, msg.Offset,string(msg.Key),string(msg.Value))? ? ? ? }deferpc.AsyncClose()? ? ? ? wg.Done()? ? ? }(pc)? }? wg.Wait()}funcmain(){? consumer()}
消費組
funcconsumerCluster(){? groupID :="group-1"config := cluster.NewConfig()? config.Group.Return.Notifications =trueconfig.Consumer.Offsets.CommitInterval =1* time.Second? config.Consumer.Offsets.Initial = sarama.OffsetNewest//初始從最新的offset開始c, err := cluster.NewConsumer(strings.Split("172.20.3.13:30901",","),groupID, strings.Split("test0",","), config)iferr !=nil{? ? ? glog.Errorf("Failed open consumer: %v", err)return}deferc.Close()gofunc(c *cluster.Consumer){? ? ? errors := c.Errors()? ? ? noti := c.Notifications()for{select{caseerr := -errors:? ? ? ? ? ? glog.Errorln(err)case-noti:? ? ? ? }? ? ? }? }(c)formsg :=rangec.Messages() {? ? ? fmt.Printf("Partition:%d, Offset:%d, key:%s, value:%s\n", msg.Partition, msg.Offset,string(msg.Key),string(msg.Value))? ? ? c.MarkOffset(msg,"")//MarkOffset 并不是實時寫入kafka,有可能在程序crash時丟掉未提交的offset}}funcmain(){goconsumerCluster()}
3.4. 生產者
同步生產者
packagemainimport("fmt""github.com/Shopify/sarama")funcmain(){? config := sarama.NewConfig()? config.Producer.RequiredAcks = sarama.WaitForAll//賦值為-1:這意味著producer在follower副本確認接收到數(shù)據(jù)后才算一次發(fā)送完成。config.Producer.Partitioner = sarama.NewRandomPartitioner//寫到隨機分區(qū)中,默認設置8個分區(qū)config.Producer.Return.Successes =truemsg := sarama.ProducerMessage{}? msg.Topic =`test0`msg.Value = sarama.StringEncoder("Hello World!")? client, err := sarama.NewSyncProducer([]string{"172.20.3.13:30901"}, config)iferr !=nil{? ? ? fmt.Println("producer close err, ", err)return}deferclient.Close()? pid, offset, err := client.SendMessage(msg)iferr !=nil{? ? ? fmt.Println("send message failed, ", err)return}? fmt.Printf("分區(qū)ID:%v, offset:%v \n", pid, offset)}
異步生產者
funcasyncProducer(){? config := sarama.NewConfig()? config.Producer.Return.Successes =true//必須有這個選項config.Producer.Timeout =5* time.Second? p, err := sarama.NewAsyncProducer(strings.Split("172.20.3.13:30901",","), config)deferp.Close()iferr !=nil{return}//這個部分一定要寫,不然通道會被堵塞gofunc(p sarama.AsyncProducer){? ? ? errors := p.Errors()? ? ? success := p.Successes()for{select{caseerr := -errors:iferr !=nil{? ? ? ? ? ? ? glog.Errorln(err)? ? ? ? ? ? }case-success:? ? ? ? }? ? ? }? }(p)for{? ? ? v :="async: "+ strconv.Itoa(rand.New(rand.NewSource(time.Now().UnixNano())).Intn(10000))? ? ? fmt.Fprintln(os.Stdout, v)? ? ? msg := sarama.ProducerMessage{? ? ? ? Topic: topics,? ? ? ? Value: sarama.ByteEncoder(v),? ? ? }? ? ? p.Input() - msg? ? ? time.Sleep(time.Second *1)? }}funcmain(){goasyncProducer()select{? ? ? }}
3.5. 結果展示-
同步生產打?。?/p>
分區(qū)ID:0,offset:90
消費打?。?/p>
Partition:0,Offset:90,key:,value:Hello World!
異步生產打?。?/p>
async:7272async:7616async:998
消費打?。?/p>
Partition:0,Offset:91,key:,value:async:7272Partition:0,Offset:92,key:,value:async:7616Partition:0,Offset:93,key:,value:async:998
文章標題:go語言kafak,go語言kafka
文章分享:http://chinadenli.net/article26/hddijg.html
成都網站建設公司_創(chuàng)新互聯(lián),為您提供網站內鏈、App設計、電子商務、網站收錄、用戶體驗、營銷型網站建設
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)