總結一下用golang
寫的服務中接入kafka
消息隊列的記錄和有用鏈接:
golang
有兩個主流的kafka lib
, sarama和confluent-kafka-go, 在編譯運行時均需要用到gcc
。構建鏡像需要加入apk add build-base
- 關於consumer, consumer group, partition,replicate等關係, 在官網已有圖文並茂解釋。
- 搭建單
broker
的測試kafka
集羣很方便, 下面是可用的docker-compose.yaml
version: '2'
services:
zookeeper:
image: wurstmeister/zookeeper
ports:
- "2181:2181"
kafka:
build: .
image: wurstmeister/kafka
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "9092:9092"
- "29092:29092"
environment:
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_LISTENERS: PLAINTEXT://:9092,PLAINTEXT_HOST://:29092
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
kafka-manager:
image: sheepkiller/kafka-manager
environment:
ZK_HOSTS: zookeeper
ports:
- "9000:9000"
鏡像wurstmeister/kafka
在下載失敗時多試幾次。另外用windows
主機連接以上測試kafka
可能會有域名解析錯誤, 此時可以修改windows
的host
文件。
開發實施:
Publisher 信息發佈模塊
參考sarama的example, 操作的簡單程度與將key/value
鍵值對放到redis
類似。若沒有特殊要求, 以下的簡單配置便能滿足生產需求:
[kafka]
brokers = ["xxx.xxx.xxx.xxx:9092,"xxx.xxx.xxx.xxx:9092","xxx.xxx.xxx.xxx:9092"]
verbose = true
max_retry = 10
flush_frenquency = 500
topic = "xxxx"
publisher
可分佈式多實例部署和運行, kafka
會處理多實例寫入問題。
Consumer 消費者模塊
參考sarama consumer group的example,sarama
提供kafka consumer group
的接口, 將example
改爲從配置文件讀入, 關注consumer group
的配置即可。
brokers =["xxx.xxx.xxx.xxx:9092,"xxx.xxx.xxx.xxx:9092","xxx.xxx.xxx.xxx:9092"]
group = "xxx"
topics = ["xxx"] # topic to be subscribed
clientID = "xxx"
verbose = true # debug info output
oldest = true # read from oldest log
注意:
example
可以以多實例運行, 如一個topic
有6
個partition
, 如以3
實例的形式運行該consumer group
代碼段的進程, 查看管理界面的consumer group
,會出現以下情況:
即consumer group
已處理好加組,partition
上的消息分配和load balancing
等問題。- 隊列的信息會過期被刪除(
kafka
集羣配置,如kafkaManagedOffsetGroupExpireDays
, 和topic
的retention.ms
), 過期後LogSize
不會變, 只是當新的consumer group
加入的時候,即使consumer group
的配置使用的是oldest
, 但是consumer
只能從被刪除的後隊列的最舊的offset讀起。 - 若需要避免因服務本身或
consumer group
重啓而重複消費信息, 必須將已讀信息標記爲已讀, 如sarama
的session.MarkMessage(message, "")
, 否則在oldest = true
情況下, 應用實例的週期變化(重啓等)會引起重複消費。 順帶一提python
的lib
, 用的是commit, - 通過直接查看
kafka
原生個管理UI
點擊Consumer
板塊即可直接查看lag
, 可通過彈性控制consumer group
進程數確保及時消費。
關於kafka connect
kafka connect 可以幫助用戶將既有系統的數據轉換成數據流。如MySql -> kafka
- 序列化和反序列化協議使用Protobuf,降低解析開銷。
- 對於
MySql(producer) -> kafka -> subscriber
,subscriber
可以捕捉的db
的create(insert)\delete\update
等事件。舉例,subscriber
可過濾獲得insert
事件,即可獲得MySql db
的數據增量, 實現一些離線業務的計算和統計等。
關於kafka
的使用場景
web service
處理請求, 將需要分析或統計的數據以異步線程的調用producer
入隊, 額外的數據分析進程訂閱相關topic
作離線分析。 這種場景將數據分析業務與主要業務解耦, 對與離線分析進程, 也可以通過彈性控制其進程實例數,做到貼近實時統計分析效果。對分析結果存疑時, 也可通過變更consumer group
的辦法對數據重新消費和統計。