最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

GoLang日志監(jiān)控系統(tǒng)實(shí)現(xiàn)

 更新時(shí)間:2022年12月15日 10:08:21   作者:上后左愛(ài)  
這篇文章主要介紹了GoLang日志監(jiān)控系統(tǒng)的實(shí)現(xiàn)流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧

日志監(jiān)控系統(tǒng)

Nginx(日志文件) -> log_process (實(shí)時(shí)讀取解析寫(xiě)入) -> influxdb(存儲(chǔ)) ->grafana(前端日志展示器)

influxdb 屬于GO語(yǔ)言編寫(xiě)的開(kāi)源的時(shí)序型數(shù)據(jù),著力于高性能 查詢與存儲(chǔ)時(shí)序型數(shù)據(jù),influxdb 廣泛的應(yīng)用于存儲(chǔ)系統(tǒng)的監(jiān)控?cái)?shù)據(jù),IOT行業(yè)的實(shí)時(shí)數(shù)據(jù)。

目前市面上流行 TSDB(時(shí)序型處理數(shù)據(jù)庫(kù)):influxDB, TimescaleDB, QuestDBinfluxDB 類似于NOSQL體驗(yàn),自動(dòng)適合標(biāo)記集模型的技術(shù)的數(shù)據(jù)集;TimescaleDB 與 postgreSQL 兼容, 更加適合物聯(lián)網(wǎng)數(shù)據(jù),與PostgreSQL更好的兼容QuestDB: 支持InfluxDB內(nèi)聯(lián)協(xié)議和PostgreSQL, 但是生態(tài)問(wèn)題比較大

項(xiàng)目簡(jiǎn)答介紹

本日志系統(tǒng) DEMO,但是可以直接使用到生產(chǎn)環(huán)境上面,使用LOG_Process 讀取Nginx ./Access.log, 使用influxDB 進(jìn)行存取

log_process -path ./access.log influxdsn http://127.0.0.1:8086@imooc@imoocpass@immoc@s

常見(jiàn)并發(fā)模型

  • 解決C10k 的問(wèn)題 采用異步非阻塞的模型(Nginx, libevent, NodeJS)-- 問(wèn)題 復(fù)雜度高 大量回調(diào)函數(shù)
  • 協(xié)程(Go,Erlang, lua): 協(xié)線性函數(shù)一樣寫(xiě)代碼;理解根加輕量級(jí)別的線程
  • 程序并行執(zhí)行 go foo() // 執(zhí)行函數(shù)
  • mgs:= <- c 多個(gè)gorountine 需要進(jìn)行通信
  • select 從多個(gè)channel 中讀取數(shù)據(jù) ,多個(gè) channel 隨機(jī)選擇一個(gè)進(jìn)行消費(fèi) 
  • 并發(fā): 一個(gè)任務(wù)通過(guò)調(diào)度器讓任務(wù)看起來(lái)運(yùn)行 屬于單核CPU(邏輯運(yùn)行)對(duì)于IO密集型比較友好
  • 并行:任務(wù)真正的運(yùn)行

在go 語(yǔ)言中 并發(fā)執(zhí)行 ,使用三個(gè)不同 gorountine, 一個(gè)負(fù)責(zé)裝填,一個(gè)負(fù)責(zé)運(yùn)輸,一個(gè)負(fù)責(zé)處理 ,讓程序并發(fā)的運(yùn)行起來(lái),讓任務(wù)更加的職責(zé)單一化 這種思想 也可以將 日志解析讀取,寫(xiě)入模塊進(jìn)行單獨(dú)小模塊,每個(gè)模塊讓使用gorountine ,通過(guò)channel 數(shù)據(jù)交互,至于這么多gorountine 是在一個(gè)CPU調(diào)度執(zhí)行還是分配到多個(gè)CPU上進(jìn)行執(zhí)行 ,取決于系統(tǒng).

go 語(yǔ)言有自己的調(diào)度器, go fun() 屬于一個(gè)獨(dú)立的工作單元,go的調(diào)度器,根據(jù)每個(gè)可用的物理處理器分配一個(gè)邏輯處理器,通過(guò)這個(gè)邏輯處理器對(duì) 獨(dú)立單元進(jìn)行處理,
通過(guò)設(shè)置: runtime.GOMAXPROCS(1)//給調(diào)度器分配多小個(gè)具體的邏輯處理器
一臺(tái)服務(wù)器的 物理處理器越多 ,go 獲取到邏輯處理器也越多,導(dǎo)致器允許速度越快。 參考:傳送門(mén)

系統(tǒng)架構(gòu)

日志解析的基本流程化的偽函數(shù),如下的函數(shù)有兩個(gè)缺陷,解析介入和解析后輸出只能寫(xiě)死,所以需要進(jìn)行擴(kuò)展,接口方式進(jìn)行擴(kuò)展

package main
import (
	"fmt"
	"strings"
	"time"
)
/**
* 日志解析系統(tǒng)分為: 解析,讀取,寫(xiě)入
 */
type LogProcess struct {
	path        string      // 讀取文件路徑
	influxDBDsn string      // influx data source
	rc          chan string // read module to process
	wc          chan string // process to influx
}
// 返回函數(shù)使用 指針, 結(jié)構(gòu)體很大 不需要進(jìn)行拷貝 性能優(yōu)化
func (l *LogProcess) ReadFromFile() {
	// 文件讀取模塊
	line := "message"
	l.rc <- line
}
func (l *LogProcess) Process() {
	// 文件解析模塊
	data := <-l.rc
	l.wc <- strings.ToUpper(data)
}
func (l *LogProcess) writeToInfluxDB() {
	fmt.Println(<-l.wc)
}
func main() {
	// lp 引用類型
	lp := &LogProcess{
		path:        "./tmp/access.log",
		influxDBDsn: "username&password...",
		rc:          make(chan string),
		wc:          make(chan string),
	}
	// tree goroutine run
	go lp.ReadFromFile()
	go lp.Process()
	// 需要定義 chan 將 Process 數(shù)據(jù) 傳遞給 influxDB
	go lp.writeToInfluxDB()
	time.Sleep(2 * time.Second)
}

接口方式約束 輸入和輸出 進(jìn)行優(yōu)化

package main
import (
	"fmt"
	"strings"
	"time"
)
/**
* 日志解析系統(tǒng)分為: 解析,讀取,寫(xiě)入
 */
type LogProcess struct {
	rc    chan string // read module to process
	wc    chan string // process to influx
	read  Read
	write Writer
}
func (l *LogProcess) Process() {
	// 文件解析模塊
	data := <-l.rc
	l.wc <- strings.ToUpper(data)
}
type Writer interface {
	writer(wc chan string)
}
type WriteToInfluxDB struct {
	influxDBDsn string // influx data source
}
func (w *WriteToInfluxDB) writer(wc chan string) {
	fmt.Println(<-wc)
}
type Read interface {
	read(rc chan string)
}
type ReadFromFile struct {
	path string // 讀取文件
}
func (r *ReadFromFile) read(rc chan string) {
	// 讀取模塊
	line := "message"
	rc <- line
}
func main() {
	// lp 引用類型
	r := &ReadFromFile{
		path: "./tmp/access.log",
	}
	w := &WriteToInfluxDB{
		influxDBDsn: "username&password"}
	lp := &LogProcess{
		rc:    make(chan string),
		wc:    make(chan string),
		read:  r,
		write: w,
	}
	// 通過(guò)接口方式 約束其功能
	go lp.read.read(lp.rc)
	go lp.Process()
	go lp.write.writer(lp.wc)
	// 通過(guò)參數(shù)注入方式
	time.Sleep(2 * time.Second)
}

讀取模塊具體實(shí)現(xiàn)

從上次讀取光標(biāo)后開(kāi)始逐行進(jìn)行讀取,無(wú)需每次都全部文件讀取

package main
import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
	"time"
)
/**
* 日志解析系統(tǒng)分為: 解析,讀取,寫(xiě)入
 */
type LogProcess struct {
	rc    chan []byte // read module to process
	wc    chan string // process to influx
	read  Read
	write Writer
}
func (l *LogProcess) Process() {
	// 文件解析模塊
	for v := range l.rc {
		l.wc <- strings.ToUpper(string(v))
	}
}
type Writer interface {
	writer(wc chan string)
}
type WriteToInfluxDB struct {
	influxDBDsn string // influx data source
}
func (w *WriteToInfluxDB) writer(wc chan string) {
	// wc 通道另外一種讀取方式
	for x := range wc {
		fmt.Println(x)
	}
}
type Read interface {
	read(rc chan []byte)
}
type ReadFromFile struct {
	path string // 讀取文件
}
func (r *ReadFromFile) read(rc chan []byte) {
	// 實(shí)時(shí)系統(tǒng): 從文件末尾逐行進(jìn)行讀取
	f, err := os.Open(r.path)
	if err != nil {
		panic(fmt.Sprintln("open file error:%s", err.Error()))
	}
	// 文件末尾最開(kāi)始進(jìn)行讀取
	f.Seek(0, 2)
	rd := bufio.NewReader(f)
	for {
		line, err := rd.ReadBytes('\n')
		if err == io.EOF {
			// d讀取到文件末尾, 日志還沒(méi)有寫(xiě)入
			time.Sleep(500 * time.Millisecond)
			continue
		} else if err != nil {
			panic(fmt.Sprintln("ReadBytes error:%s", err.Error()))
		}
		rc <- line[:len(line)-1]
	}
}
func main() {
	// lp 引用類型
	r := &ReadFromFile{
		path: "H:\\code\\goprogarm\\src\\access.log",
	}
	w := &WriteToInfluxDB{
		influxDBDsn: "username&password"}
	lp := &LogProcess{
		rc:    make(chan []byte),
		wc:    make(chan string),
		read:  r,
		write: w,
	}
	// 通過(guò)接口方式 約束其功能
	go lp.read.read(lp.rc)
	go lp.Process()
	go lp.write.writer(lp.wc)
	// 通過(guò)參數(shù)注入方式
	time.Sleep(100 * time.Second)
}

日志解析模塊

  • 沖Read Chan 中讀取每一行數(shù)據(jù)
  • 正則方式提取所需要的監(jiān)控?cái)?shù)據(jù)
  • 將數(shù)據(jù)寫(xiě)入到influxDB
package main
import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"regexp"
	"strconv"
	"time"
)
/**
* 日志解析系統(tǒng)分為: 解析,讀取,寫(xiě)入
 */
type LogProcess struct {
	rc    chan []byte // read module to process
	wc    chan *Message // process to influx
	read  Read
	write Writer
}
//日志寫(xiě)入結(jié)構(gòu)體
type Message struct {
	TimeLocal time.Time
	BytesSent int
	Path, Method, Scheme, Status string
	UpstreamTime, RequestTime float64
}
func (l *LogProcess) Process() {
	// 通過(guò)正則表達(dá)式進(jìn)行解析數(shù)據(jù)
	r := regexp.MustCompile(`(\s*)`)
	loc, _ := time.LoadLocation("Asia/shanghai")
	// 文件解析模塊
	for v := range l.rc {
		ret := r.FindStringSubmatch(string(v))
		if len(ret) != 13 {
			log.Println("FindStringSub match fail:", string(v))
			continue
		}
		message := &Message{
		}
		location, err := time.ParseInLocation("02/Jan/2006:15:04:05 +0000", ret[4], loc)
		if err != nil {
			log.Println("ParseInLocation fail:", err.Error(), ret[4])
		}
		message.TimeLocal = location
		// 字符串類型轉(zhuǎn)換成int
		atoi, err := strconv.Atoi(ret[8])
		if err != nil {
			log.Println("strconv.Atoi fail:", err.Error(), ret[4])
		}
		message.BytesSent = atoi
		l.wc <- message
	}
}
type Writer interface {
	writer(wc chan *Message)
}
type WriteToInfluxDB struct {
	influxDBDsn string // influx data source
}
func (w *WriteToInfluxDB) writer(wc chan *Message) {
	// wc 通道另外一種讀取方式
	for x := range wc {
		fmt.Println(x)
	}
}
type Read interface {
	read(rc chan []byte)
}
type ReadFromFile struct {
	path string // 讀取文件
}
func (r *ReadFromFile) read(rc chan []byte) {
	// 實(shí)時(shí)系統(tǒng): 從文件末尾逐行進(jìn)行讀取
	f, err := os.Open(r.path)
	if err != nil {
		panic(fmt.Sprintf("open file error:%s\n", err.Error()))
	}
	// 文件末尾最開(kāi)始進(jìn)行讀取
	f.Seek(0, 2)
	rd := bufio.NewReader(f)
	for {
		line, err := rd.ReadBytes('\n')
		if err == io.EOF {
			// d讀取到文件末尾, 日志還沒(méi)有寫(xiě)入
			time.Sleep(500 * time.Millisecond)
			continue
		} else if err != nil {
			panic(fmt.Sprintf("ReadBytes error:%s\n", err.Error()))
		}
		rc <- line[:len(line)-1]
	}
}
func main() {
	// lp 引用類型
	r := &ReadFromFile{
		path: "H:\\code\\goprogarm\\src\\access.log",
	}
	w := &WriteToInfluxDB{
		influxDBDsn: "username&password"}
	lp := &LogProcess{
		rc:    make(chan []byte),
		wc:    make(chan *Message),
		read:  r,
		write: w,
	}
	// 通過(guò)接口方式 約束其功能
	go lp.read.read(lp.rc)
	go lp.Process()
	go lp.write.writer(lp.wc)
	// 通過(guò)參數(shù)注入方式
	time.Sleep(100 * time.Second)
}

到此這篇關(guān)于GoLang日志監(jiān)控系統(tǒng)實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)GoLang日志監(jiān)控內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang之sync.Pool使用詳解

    Golang之sync.Pool使用詳解

    這篇文章主要介紹了Golang之sync.Pool使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Golang中struct{}和struct{}{}的區(qū)別解析

    Golang中struct{}和struct{}{}的區(qū)別解析

    這篇文章主要介紹了Golang中struct{}和struct{}{}的區(qū)別,通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • 以Golang為例詳解AST抽象語(yǔ)法樹(shù)的原理與實(shí)現(xiàn)

    以Golang為例詳解AST抽象語(yǔ)法樹(shù)的原理與實(shí)現(xiàn)

    AST?使用樹(shù)狀結(jié)構(gòu)來(lái)表達(dá)編程語(yǔ)言的結(jié)構(gòu),樹(shù)中的每一個(gè)節(jié)點(diǎn)都表示源碼中的一個(gè)結(jié)構(gòu),本文將以GO語(yǔ)言為例,為大家介紹一下AST抽象語(yǔ)法樹(shù)的原理與實(shí)現(xiàn),希望對(duì)大家有所幫助
    2024-01-01
  • Go中的錯(cuò)誤和異常處理最佳實(shí)踐方法

    Go中的錯(cuò)誤和異常處理最佳實(shí)踐方法

    這篇文章主要介紹了Go中的錯(cuò)誤和異常處理最佳實(shí)踐方法,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容戒殺,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • 詳解golang?defer?閉包?匿名函數(shù)

    詳解golang?defer?閉包?匿名函數(shù)

    這篇文章主要介紹了golang?defer?閉包?匿名函數(shù)的相關(guān)知識(shí),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • goland?-sync/atomic原子操作小結(jié)

    goland?-sync/atomic原子操作小結(jié)

    這篇文章主要介紹了goland?-sync/atomic原子操作,原子操作能夠保證執(zhí)行期間是連續(xù)且不會(huì)被中斷(變量不會(huì)被其他修改,mutex可能存在被其他修改的情況),本文給大家介紹的非常詳細(xì),需要的朋友參考下
    2022-08-08
  • Golang并發(fā)編程深入分析

    Golang并發(fā)編程深入分析

    golang中的并發(fā),是函數(shù)相互獨(dú)立運(yùn)行的能力,goroutines是并發(fā)運(yùn)行的函數(shù)。golang提供了goroutines作為并發(fā)處理的一種方式
    2022-11-11
  • 詳解Golang中Channel的高級(jí)用法

    詳解Golang中Channel的高級(jí)用法

    在Go語(yǔ)言中,chan(通道)是一種用于在不同的goroutine之間進(jìn)行通信的機(jī)制,通道可以是無(wú)緩沖的(同步的)或有緩沖的(異步的),本文給大家詳細(xì)介紹了Golang中Channel的高級(jí)用法,需要的朋友可以參考下
    2024-05-05
  • 深入探索Go?1.21中的?maps工具庫(kù)

    深入探索Go?1.21中的?maps工具庫(kù)

    隨著?Go?1.21.0?版本的發(fā)布,新增了兩個(gè)實(shí)用的泛型工具庫(kù):maps?和?slices,下面小編就帶大家一起學(xué)習(xí)一下?maps?工具庫(kù)的相關(guān)知識(shí)吧
    2023-08-08
  • GoLang分布式鎖與snowflake雪花算法

    GoLang分布式鎖與snowflake雪花算法

    這篇文章主要介紹了GoLang分布式鎖與snowflake雪花算法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2022-12-12

最新評(píng)論

庆安县| 定兴县| 精河县| 无锡市| 延安市| 徐汇区| 青铜峡市| 徐汇区| 清苑县| 荥经县| 双鸭山市| 邯郸县| 临颍县| 凉山| 乌什县| 孝感市| 紫金县| 临高县| 五常市| 高青县| 柘城县| 巴林左旗| 麟游县| 宣威市| 马公市| 徐闻县| 贵溪市| 溆浦县| 游戏| 济南市| 隆化县| 海兴县| 江门市| 舒城县| 孟村| 循化| 禹城市| 武隆县| 施秉县| 板桥市| 宜州市|