golang連接kafka消費(fèi)進(jìn)ES操作
1.首先初始化conf配置把kafka和ES的地址配置好還有一個(gè)日志方便查看
配置信息如下 用到的庫(kù)是
github.com/astaxie/beego/config [logs] log_level = debug log_path = "./logs/log_transfer.log" [kafka] server_addr = 192.168.0.134:9092 topic = nginx_log [ES] addr = http://192.168.0.134:9200/
2.讀取conf配置存取進(jìn)結(jié)構(gòu)體
type LogConfig struct {
kafkaAddr string
ESAddr string
LogPath string
LogLevel string
Topic string
}
var (
logConfig *LogConfig
)
3.讀取conf配置代碼如下
func initConfig(conftype string,filename string)(err error) {
conf, err := config. NewConfig(conftype,filename)
if err != nil {
fmt. Println( "new config faild,err:",err)
return
}
logConfig = &LogConfig{}
logConfig.LogLevel = conf. String( "logs::log_level")
if len(logConfig.LogLevel) == 0 {
logConfig.LogLevel = "debug"
}
logConfig.LogPath = conf. String( "logs::log_path")
if len(logConfig.LogPath) == 0 {
logConfig.LogPath = "./logs"
}
logConfig.kafkaAddr = conf. String( "kafka::server_addr")
if len(logConfig.kafkaAddr) == 0 {
err = fmt. Errorf( "invalid kafka addr err")
return
}
logConfig.ESAddr = conf. String( "ES::addr")
if len(logConfig.ESAddr) == 0 {
err = fmt. Errorf( "invalid ES addr err")
return
}
logConfig.Topic = conf. String( "kafka::topic")
if len(logConfig.Topic) == 0 {
err = fmt. Errorf( "invalid topic addr err")
return
}
return
}
4.完成了initConfig的初始化
5.初始化initLogger
func convertLogLevel(level string) int {
switch(level) {
case "debug":
return logs.LevelDebug
case "warn":
return logs.LevelWarn
case "info":
return logs.LevelInfo
case "trace":
return logs.LevelTrace
}
return logs.LevelDebug
}
func initLogger(logpath string, logLevel string) (err error) {
config := make( map[ string] interface{})
config[ "filename"] = logpath
config[ "level"] = convertLogLevel(logLevel)
configStr, err := json. Marshal(config)
if err!= nil {
fmt. Println( "marshal failed,err:",err)
return
}
logs. SetLogger(logs.AdapterFile, string(configStr))
return
}
6.初始化kafka
type KafkaClient struct {
client sarama.Consumer
addr string
topic string
wg sync.WaitGroup
}
var (
kafkaClient *KafkaClient
)
func initKafKa(addr string,topic string)(err error) {
kafkaClient = &KafkaClient{}
consumer, err := sarama. NewConsumer(strings. Split(addr, ","), nil)
if err != nil {
logs. Error( "Failed to strat consumer :",err)
return
}
kafkaClient.client = consumer
kafkaClient.addr = addr
kafkaClient.topic = topic
return
}
7.初始化ES
gopkg.in/olivere/elastic.v2 // 這個(gè)是操作ES的庫(kù)
type LogMessage struct {
App string
Topic string
Message string
}
var (
esClient *elastic.Client
)
func initES(addr string)(err error) {
client, err := elastic. NewClient(elastic. SetSniff( false),elastic. SetURL(addr))
if err != nil {
fmt. Println( "connect es error",err)
return
}
esClient = client
return
}
8.干活把kafka的數(shù)據(jù)寫(xiě)入ES
github.com/Shopify/sarama 這個(gè)是操作kafka的驅(qū)動(dòng)庫(kù)
func run()(err error) {
fmt. Println( "run")
partitionList, err := kafkaClient.client. Partitions(kafkaClient.topic)
if err != nil {
logs. Error( "ini failed ,err:%v",err)
fmt. Printf( "ini failed ,err:%v",err)
return
}
for partition := range partitionList {
fmt. Println( "for進(jìn)入")
pc, errRet := kafkaClient.client. ConsumePartition(kafkaClient.topic, int32(partition),sarama.OffsetNewest)
if errRet != nil {
err = errRet
logs. Error( "Failed to start consumer for partition %d: %s \n ",partition,err)
fmt. Printf( "Failed to start consumer for partition %d: %s \n ",partition,err)
return
}
defer pc. AsyncClose()
fmt. Println( "馬上進(jìn)入?yún)f(xié)程")
kafkaClient.wg. Add( 1)
go func(pc sarama.PartitionConsumer){
fmt. Println( "進(jìn)來(lái)了")
for msg := range pc. Messages() {
fmt. Println( "func執(zhí)行")
logs. Debug( "Partition:%d,Offset:%d,key:%s,value:%s",msg.Partition,msg.Offset, string(msg.Key), string(msg.Value))
//fmt.Println()
err = sendToES(kafkaClient.topic,msg.Value)
if err != nil {
logs. Warn( "send to es failed,err:%v",err)
}
}
kafkaClient.wg. Done()
}(pc)
}
kafkaClient.wg. Wait()
fmt. Println( "協(xié)程執(zhí)行完畢")
return
}
上面代碼是讀kafka消費(fèi)數(shù)據(jù)通過(guò)sendToES這個(gè)函數(shù)發(fā)送至ES里面
sendToES代碼如下
func sendToES(topic string,data [] byte) (err error) {
msg := &LogMessage{}
msg.Topic = topic
msg.Message = string(data)
_, err = esClient. Index().
Index(topic).
Type(topic).
BodyJson(msg).
Do()
if err != nil {
return
}
return
}
Index就是索引名稱(chēng)
index().type().bodyjson().do()這樣的寫(xiě)法是鏈?zhǔn)綀?zhí)行操作
9.寫(xiě)完了基本操作后 再寫(xiě)一個(gè)模擬寫(xiě)入數(shù)據(jù)進(jìn)kafka的數(shù)據(jù) 代碼如下
func main() {
config := sarama. NewConfig()
config.Producer.RequiredAcks = sarama.WaitForAll
config.Producer.Partitioner = sarama.NewRandomPartitioner
config.Producer.Return.Successes = true
client, err := sarama. NewSyncProducer([] string{ "127.0.0.1:9092"}, config)
if err != nil {
fmt. Println( "producer close,err:", err)
return
}
defer client. Close()
var n int= 0
for {
n++
msg := &sarama.ProducerMessage{}
msg.Topic = "nginx_log"
msg.Value = sarama. StringEncoder( "this is a good test,hello maomaoChong!!," + strconv. Itoa(n))
pid, offset, err := client. SendMessage(msg)
if err != nil {
fmt. Println( "send message failed,", err)
return
}
fmt. Printf( "pid:%v offset:%v \n ", pid, offset)
time. Sleep(time.Second * 2)
}
}
這個(gè)就是生產(chǎn)者往kafka里面寫(xiě)入數(shù)據(jù)進(jìn)去消費(fèi)
10.我們啟動(dòng)我們的kafka 注意kafka依賴(lài)于zookeeper 先啟動(dòng)ZK然后啟動(dòng)kafka
我這里用的是zookeeper-3.4.12網(wǎng)上有下載
啟動(dòng)ZK

ZK已經(jīng)成功啟動(dòng)
11.啟動(dòng)kafka 我這里是kafka_2.11-1.1.0
.\bin\windows\kafka-server-start.bat .\config\server.properties

kafka已經(jīng)跑起來(lái)了
12.把kafka消費(fèi)測(cè)試端也啟動(dòng)
.\bin\windows\kafka-console-consumer.bat --topic nginx_log --zookeeper 127.0.0.1 2181

消費(fèi)端啟動(dòng)成功 一直等待數(shù)據(jù)進(jìn)來(lái)消費(fèi)
13.然后我們把ES 和Kib 都啟動(dòng)了

這是我們的ES版本是5.5.1的 已經(jīng)跑起來(lái)了 接著啟動(dòng)我們的kib
kib里面有個(gè)配置config下面的叫kibana.yml里面設(shè)置好ES的地址和端口就處于監(jiān)聽(tīng)ES狀態(tài)
啟動(dòng)kib有點(diǎn)慢 稍微等一下就好

此時(shí)啟動(dòng)好了kib
14.測(cè)試kib是否啟動(dòng)
默認(rèn)地址是http://localhost:5601

進(jìn)入成功 確定沒(méi)問(wèn)題
15.編譯我們的代碼 寫(xiě)數(shù)據(jù)進(jìn)kafka

從上面看我們知道一個(gè)再寫(xiě) 一個(gè)再消費(fèi)
16.編譯運(yùn)行我們把kafka寫(xiě)入進(jìn)ES里面的代碼

運(yùn)行了 這里就把kafka消費(fèi)的數(shù)據(jù) 寫(xiě)入進(jìn)ES里面
17.我們看一下數(shù)據(jù)是否有 進(jìn)入kib

我們看到有數(shù)據(jù)了 已經(jīng)成功了~
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
go?micro微服務(wù)proto開(kāi)發(fā)安裝及使用規(guī)則
這篇文章主要為大家介紹了go?micro微服務(wù)proto開(kāi)發(fā)中安裝Protobuf及基本規(guī)范字段的規(guī)則詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Golang科學(xué)計(jì)數(shù)法轉(zhuǎn)換string數(shù)字輸出的實(shí)現(xiàn)
最近接手一個(gè)商城運(yùn)單號(hào)模塊,接手后發(fā)現(xiàn)有部分運(yùn)單號(hào)返回給前端是按照科學(xué)計(jì)數(shù)法的方式返回,本文就介紹一下Golang科學(xué)計(jì)數(shù)法轉(zhuǎn)換string數(shù)字輸出,感興趣的可以了解一下2021-07-07
GoFrame代碼優(yōu)化gconv類(lèi)型轉(zhuǎn)換避免重復(fù)定義map
這篇文章主要為大家介紹了GoFrame代碼優(yōu)化gconv類(lèi)型轉(zhuǎn)換避免重復(fù)定義map示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
idea搭建go環(huán)境實(shí)現(xiàn)go語(yǔ)言開(kāi)發(fā)
這篇文章主要給大家介紹了關(guān)于idea搭建go環(huán)境實(shí)現(xiàn)go語(yǔ)言開(kāi)發(fā)的相關(guān)資料,文中通過(guò)圖文介紹以及代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用go具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01
golang連接MongoDB數(shù)據(jù)庫(kù)及數(shù)據(jù)庫(kù)操作指南
MongoDB是Nosql中常用的一種數(shù)據(jù)庫(kù),下面這篇文章主要給大家介紹了關(guān)于golang連接MongoDB數(shù)據(jù)庫(kù)及數(shù)據(jù)庫(kù)操作的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09

