上週分享了Kafka性能測試初探的Java版本,有讀者留言說太簡單,內容比較水。這裏澄清一下,是我學得比較水。文章定位就是一篇使用Java語言的Kafka Client客戶端進行簡單操作演示,然後模擬一下簡單場景的性能測試。其中深入學習Kafka的可以隨處搜到很權威實用的資料,有深入學習需求的可以自行尋找。
好久沒有寫Go了,這才突然覺察到,又重新複習了一波Go語言的基礎語法。順帶着之前留下的好習慣,每個學習的框架和工具都用Java和Go寫一遍。這次也分享一下Go語言的Kafka基礎入門,以及生產者的簡單測試場景。
我用的是shopify出的sarama,依賴如下github.com/Shopify/sarama v1.38.1
。在搜資料的過程中,還發現有使用其他客戶端的,選擇挺多。
Kafka配置
Sarama框架中的生產者和消費者的配置類是一個,不太清楚這麼設計的意圖,兩個配置重合度並不高,在Sarama中也是分開配置,但使用了同一個配置類。
生產者配置:
config := sarama.NewConfig()
config.Producer.Return.Successes = true
config.Producer.Return.Errors = true
config.Producer.RequiredAcks = sarama.NoResponse
config.Producer.Compression = sarama.CompressionLZ4
config.Producer.Timeout = time.Duration(50) * time.Millisecond
config.Producer.Retry.Max = 3
消費者配置:
config := sarama.NewConfig()
config.Consumer.Offsets.AutoCommit.Enable = true
config.Consumer.Offsets.AutoCommit.Interval = 1 * time.Second
config.Consumer.Offsets.Initial = sarama.OffsetOldest
config.Consumer.Offsets.Retry.Max = 3
這裏只選擇部分參數,詳細的配置項和註釋都可以在源碼中找到,Sarama的一個好處就是註釋非常全,甚至不用看官方API文檔。
生產者
下面是生產者的代碼,相比較Java來說,我這裏增加了header的實踐,其實Java也是支持的,只是當時學的時候漏掉了這個知識點。
producer, err := sarama.NewSyncProducer([]string{"localhost:9092"}, config)
if err != nil {
log.Fatal(err)
return
}
defer func() {
// 關閉生產者
if err = producer.Close(); err != nil {
log.Fatal(err)
return
}
}()
// 定義需要發送的消息
headers := []sarama.RecordHeader{sarama.RecordHeader{
Key: []byte("funtest"),
Value: []byte("have fun ~"),
}}
msg := &sarama.ProducerMessage{
Topic: "topic_test",
Key: sarama.StringEncoder("test"),
Value: sarama.StringEncoder("ddddddddddddddddd"),
Headers: headers,
}
// 發送消息,並獲取該消息的分片、偏移量
for i := 0; i < 100; i++ {
ftool.Sleep(1000)
partition, offset, err := producer.SendMessage(msg)
if err != nil {
log.Fatal(err)
}
fmt.Printf("partition:%d offset:%d\n", partition, offset)
}
這裏官方給的實踐代碼中感覺ProducerMessage
類似於Java的org.apache.kafka.clients.producer.ProducerRecord#ProducerRecord
,也是可以指定partitionid和時間戳,以及單獨設置retries次數的。還有一個比較重要的類AsyncProducer
,暫時不探索了。
消費者
消費者使用上Go和Java差異比較大,Sarama用了channel的概念,可以一直不停止從服務端獲取消息對象,不像Java可以指定一次接受的消息數量,單次最大等待時間等。盲猜這裏channel的性能太好了吧,不需要複雜設計也能滿足需求。
consumer, err := sarama.NewConsumer([]string{"localhost:9092"}, config)
if err != nil {
fmt.Printf("fail to start consumer, err:%v\n", err)
return
}
topic := "topic_test"
partitionList, err := consumer.Partitions(topic) // 根據topic取到所有的分區
if err != nil {
fmt.Printf("fail to get list of partition:err%v\n", err)
return
}
fmt.Println(partitionList)
defer consumer.Close()
for partition := range partitionList { // 遍歷所有的分區
// 針對每個分區創建一個對應的分區消費者
log.Println(partition)
pc, err := consumer.ConsumePartition(topic, int32(partition), sarama.OffsetOldest)
if err != nil {
fmt.Printf("failed to start consumer for partition %d,err:%v\n", partition, err)
}
for msg := range pc.Messages() {
log.Println(string(msg.Value))
//log.Println(string(msg.Headers[0].Value))
}
for {
msg := <-pc.Messages()
log.Println(string(msg.Value))
}
}
後來我寫了兩種接受方式,其實都是阻塞的,如果是性能測試的時候可以使用Go中的go
關鍵字起routine來執行。
性能測試
我這之展示性能測試簡單的例子,即生產者不停地往Kafka發消息的Demo,複用了上文中的生產者代碼,下面只展示執行部分。
execute.ExecuteRoutineTimes(func() {
_, _, _ := producer.SendMessage(msg)
}, 100, 10)
執行方法ExecuteRoutineTimes是我寫的一個基於線程模型的壓測執行方法,內容如下:
// ExecuteRoutineTimes
// @Description: FunTester性能測試執行框架
// @param fun 待執行方法
// @param times 次數
// @param routine 線程數
func ExecuteRoutineTimes(fun func(), times, routine int) {
c := make(chan int) //確認所有線程都結束
key := false //用於控制所有線程一起結束
start := ftool.Milli()
for i := 0; i < routine; i++ {
go func() {
sum := 0
for i := 0; i < times; i++ {
if key {
break
}
fun()
sum++
}
key = true
c <- sum
}()
}
total := 0
for i := 0; i < routine; i++ {
num := <-c
total += num
}
end := ftool.Milli()
diff := end - start
//total := thread * times
log.Printf("總耗時: %f", float64(diff)/1000)
log.Printf("請求總數: %d", total)
log.Printf("QPS: %f", float64(total)/float64(diff)*1000.0)
}
總結起來,相比Java,Go語言相對簡單一些。如果習慣了Go語言的習慣,對於做測試來說上手要比Java快一些。再買個坑,改天測試一下兩者之間的性能差異。理論上Go要比Java好一些。
Sarama是一個用於Apache Kafka的Go語言庫。Kafka是一個分佈式流處理平臺,它可以處理大規模的數據流,並將其發佈到主題中,供其他應用程序使用。Sarama庫允許Go應用程序與Kafka集羣進行通信。它支持多個版本的Kafka協議,並提供了生產者和消費者API,以便應用程序可以輕鬆地將消息發佈到Kafka主題或從中讀取消息。Sarama還提供了一些有用的工具,如分區選擇器和負載平衡器,以幫助開發人員更好地管理Kafka消費者。