課程
/后端開發
/Go
/Go并發編程案例解析
為什么我照著敲的,去掉sleep后,它監聽哪個9193端口,但好像不是阻塞式的,執行go run log_process.go
2018-05-09
源自:Go并發編程案例解析 2-8
正在回答
大神,上面那個是log_process.go的代碼
麥可同學
坐著看太陽敲代碼 提問者 回復 麥可同學
package?main import?( ???"strings" ???"fmt" ???"time" ???"os" ???"bufio" ???"io" ???"regexp" ???"log" ???"strconv" ???"net/url" ???"flag" ???"net/http" ???//"influxdb-master/client/v2" ???"github.com/influxdata/influxdb/client/v2" ???"encoding/json" ) //?系統狀態監控 type?SystemInfo?struct?{ ???HandleLine???int?????`json:"handleLine"`???//?總處理日志行數 ???Tps??????????float64?`json:"tps"`??????????//?系統吞出量 ???ReadChanLen??int?????`json:"readChanLen"`??//?read?channel?長度 ???WriteChanLen?int?????`json:"writeChanLen"`?//?write?channel?長度 ???RunTime??????string??`json:"runTime"`??????//?運行總時間 ???ErrNum???????int?????`json:"errNum"`???????//?錯誤數 } const?( ???TypeHandleLine?=?0 ???TypeErrNum?????=?1 ) var?TypeMonitorChan?=?make(chan?int,?200) type?Monitor?struct?{ ???startTime?time.Time ???data??????SystemInfo ???tpsSli????[]int } func?(m?*Monitor)?start(lp?*LogProcess)?{ ???go?func()?{ ??????for?n?:=?range?TypeMonitorChan?{ ?????????switch?n?{ ?????????case?TypeErrNum: ????????????m.data.ErrNum?+=?1 ?????????case?TypeHandleLine: ????????????m.data.HandleLine?+=?1 ?????????} ??????} ???}() ???ticker?:=?time.NewTicker(time.Second?*?5) ???go?func()?{?//協程 ??????for?{ ?????????<-ticker.C ?????????m.tpsSli?=?append(m.tpsSli,?m.data.HandleLine) ?????????if?len(m.tpsSli)?>?2?{ ????????????m.tpsSli?=?m.tpsSli[1:] ?????????} ??????} ???}() ???http.HandleFunc("/monitor",?func(writer?http.ResponseWriter,?request?*http.Request)?{ ??????m.data.RunTime?=?time.Now().Sub(m.startTime).String() ??????m.data.ReadChanLen?=?len(lp.rc) ??????m.data.WriteChanLen?=?len(lp.wc) ??????if?len(m.tpsSli)?>=?2?{ ?????????m.data.Tps?=?float64(m.tpsSli[1]-m.tpsSli[0])?/?5 ??????} ??????ret,?_?:=?json.MarshalIndent(m.data,?"",?"\t") ??????io.WriteString(writer,?string(ret)) ???}) ???http.ListenAndServe(":9193",?nil) } type?Reader?interface?{ ???Read(rc?chan?[]byte) } type?Writer?interface?{ ???Write(wc?chan?*Message) } type?LogProcess?struct?{ ???rc?chan?[]byte ???wc?chan?*Message ???//path????????string?//讀取文件的路徑 ???//influxDBDsn?string?//influx?data?source ???read??Reader ???write?Writer } type?ReadFromToInFile?struct?{ ???path?string?//獲取文件路徑 } type?WriteFromTofluxDB?struct?{ ???influxDBDsn?string?//influx?data?source } type?Message?struct?{ ???TimeLocal????????????????????time.Time ???BytesSent????????????????????int ???Path,?Method,?Scheme,?Status?string ???UpstreamTime,?RequestTime????float64 } func?(r?*ReadFromToInFile)?Read(rc?chan?[]byte)?{ ???//讀取模塊 ???//打開文件 ???f,?err?:=?os.Open(r.path)?//返回file類型的結構體指針,因為這個結構體只能逐個讀取這個字符,所以下面會換成newreader ???if?err?!=?nil?{ ??????panic(fmt.Sprint("open?file?error:%s",?err.Error())) ???} ???//從文件末尾開始逐行讀取文件內容 ???f.Seek(0,?2)?????????????//把字符指針移動到末尾,參數2就是移動到末尾的意思 ???rd?:=?bufio.NewReader(f)?//這樣它會返回新的NewReader的類型指針,以至于可以使用更多的方法,逐行讀取 ???for?{ ??????line,?err?:=?rd.ReadBytes('\n')?//逐行讀??;又或者是讀取直到遇見換行符 ??????if?err?==?io.EOF?{?//EOf代表是文件末尾的錯誤 ?????????time.Sleep(500?*?time.Millisecond) ?????????continue ??????}?else?if?err?!=?nil?{ ?????????panic(fmt.Sprintf("ReadBytes?error:%s",?err.Error())) ??????} ??????//print(line) ??????TypeMonitorChan?<-?TypeHandleLine ??????rc?<-?line[:len(line)-1] ???} ???//rc<-line ???// ???//line?:=?"message" ???//rc?<-?line } func?(w?*WriteFromTofluxDB)?Write(wc?chan?*Message)?{ ???//寫入模塊 ???infSli?:=?strings.Split(w.influxDBDsn,?"@") ???c,?err?:=?client.NewHTTPClient(client.HTTPConfig{ ??????Addr:?????infSli[0], ??????Username:?infSli[1], ??????Password:?infSli[2], ???}) ???if?err?!=?nil?{ ??????log.Fatal(err) ???} ???defer?c.Close() ???//?Create?a?new?point?batch ???bp,?err?:=?client.NewBatchPoints(client.BatchPointsConfig{ ??????Database:??infSli[3], ??????Precision:?infSli[4], ???}) ???if?err?!=?nil?{ ??????log.Fatal(err) ???} ???//fmt.Println(<-wc) ???for?v?:=?range?wc?{ ??????//?Create?a?point?and?add?to?batch ??????tags?:=?map[string]string{"Path":?v.Path,?"Method":?v.Method,?"Scheme":?v.Scheme,?"Status":?v.Status} ??????fields?:=?map[string]interface{}{ ?????????"UpstreamTime":?v.UpstreamTime, ?????????"RequestTime":??v.RequestTime, ?????????"BytesSent":????v.BytesSent, ??????} ??????pt,?err?:=?client.NewPoint("nginx_log",?tags,?fields,?v.TimeLocal) ??????if?err?!=?nil?{ ?????????log.Fatal(err) ??????} ??????bp.AddPoint(pt) ??????//?Write?the?batch ??????if?err?:=?c.Write(bp);?err?!=?nil?{ ?????????log.Fatal(err) ??????} ??????log.Println("write?success") ??????//?Close?client?resources ??????//if?err?:=?c.Close();?err?!=?nil?{ ??????//?log.Fatal(err) ??????//} ??????//fmt.Println(v) ???} } //func?(l?*LogProcess)?ReadFromFile()?{ //?//讀取模塊 //?line?:=?"message" //?l.rc?<-?line //} func?(l?*LogProcess)?Proccess()?{ ???//?解析模塊 ???/** ???172.0.0.12?-?-?[04/Mar/2018:13:49:52?+0000]?http?"GET?/foo?query=t?HTTP/1.0"?200?2133?"-"?"KeepAliveClient"?"-"?1.005?1.854 ???*/ ???r?:=?regexp.MustCompile(`([\d\.]+)\s+([^?\[]+)\s+([^?\[]+)\s+\[([^\]]+)\]\s+([a-z]+)\s+\"([^"]+)\"\s+(\d{3})\s+(\d+)\s+\"([^"]+)\"\s+\"(.*?)\"\s+\"([\d\.-]+)\"\s+([\d\.-]+)\s+([\d\.-]+)`) ???loc,?_?:=?time.LoadLocation("Asia/Shanghai") ???for?v?:=?range?l.rc?{ ??????ret?:=?r.FindStringSubmatch(string(v)) ??????//log.Println(ret,?len(ret)) ??????if?len(ret)?!=?14?{ ?????????TypeMonitorChan?<-?TypeErrNum ?????????log.Println("FindStringSubmatch?fail:",?string(v)) ?????????continue ??????} ??????message?:=?&Message{} ??????t,?err?:=?time.ParseInLocation("02/Jan/2006:15:04:05?+0000",?ret[4],?loc) ??????if?err?!=?nil?{ ?????????TypeMonitorChan?<-?TypeErrNum ?????????log.Println("ParseInLocation?fail:",?err.Error(),?ret[4]) ?????????continue ??????} ??????message.TimeLocal?=?t ??????byteSent,?_?:=?strconv.Atoi(ret[8]) ??????message.BytesSent?=?byteSent ??????//?GET?/foo?query=t?HTTP/1.0 ??????reqSli?:=?strings.Split(ret[6],?"?") ??????if?len(reqSli)?!=?3?{ ?????????TypeMonitorChan?<-?TypeErrNum ?????????log.Println("strings.Split?fail",?ret[6]) ?????????continue ??????} ??????message.Method?=?reqSli[0] ??????u,?err?:=?url.Parse(reqSli[1]) ??????if?err?!=?nil?{ ?????????log.Println("url?parse?fail:",?err) ?????????TypeMonitorChan?<-?TypeErrNum ?????????continue ??????} ??????message.Path?=?u.Path ??????message.Scheme?=?ret[5] ??????message.Status?=?ret[7] ??????upstreamTime,?_?:=?strconv.ParseFloat(ret[12],?64) ??????requestTime,?_?:=?strconv.ParseFloat(ret[13],?64) ??????message.UpstreamTime?=?upstreamTime ??????message.RequestTime?=?requestTime ??????l.wc?<-?message ???} } //func?(l?*LogProcess)?WriteToInfluxDB()?{ //?//寫入模塊 //?fmt.Println(<-l.wc) //?fmt.Println(<-l.wc) //} func?main()?{ ???var?path,?influxDsn?string ???flag.StringVar(&path,?"path",?"./access.log",?"read?file?path") ???flag.StringVar(&influxDsn,?"influxDsn",?"http://127.0.0.1:8086@root@101@imooc@s",?"influx?data?source") ???flag.Parse() ???r?:=?&ReadFromToInFile{ ??????path:?path, ???} ???w?:=?&WriteFromTofluxDB{ ??????influxDBDsn:?influxDsn, ???} ???lp?:=?&LogProcess{ ??????rc:????make(chan?[]byte,?200), ??????wc:????make(chan?*Message,?200), ??????read:??r, ??????write:?w, ???} ???//go?lp.ReadFromFile()?//lp是引用類型,出于性能考慮這樣做。本來這里應該這樣寫?go?(*lp).ReadFromFile(), ???////?但goland編輯器對此優化,寫成go?lp.ReadFromFile(),也能達到上面一樣的效果。知道他是個結構體。更利于閱讀 ???//go?lp.Proccess() ???//go?lp.WriteToInfluxDB() ???//time.Sleep(1?*?time.Second) ???go?lp.read.Read(lp.rc)?//lp是引用類型,出于性能考慮這樣做。本來這里應該這樣寫?go?(*lp).ReadFromFile(), ???//?但goland編輯器對此優化,寫成go?lp.ReadFromFile(),也能達到上面一樣的效果。知道他是個結構體。更利于閱讀 ???for?i?:=?0;?i?<?2;?i++?{ ??????go?lp.Proccess() ???} ???for?i?:=?0;?i?<?4;?i++?{ ??????go?lp.write.Write(lp.wc) ???} ???// ???//m?:=?&Monitor{ ???//?startTime:?time.Now(), ???//?data:??????SystemInfo{}, ???//} ???//m.start(lp) ???m?:=?&Monitor{ ??????startTime:?time.Now(), ??????data:??????SystemInfo{}, ???} ???m.start(lp) ???//time.Sleep(30?*?time.Second) }
舉報
課程帶你通過一個真實的線上日志監控系統學習Golang以及并發的編程思想。
1 回答實施監聽文件變化的方式的問題
2 回答請問老師,什么時候出go web方面的課程?
3 回答僅僅輸出了第一行,第二行就報錯
7 回答為什么我引入不了這個包"github.com/influxdata/influxdb/client/v2"
2 回答并發的去讀nginx最后一行日志會不會產生讀取日志重復的問題
Copyright ? 2025 imooc.com All Rights Reserved | 京ICP備12003892號-11 京公網安備11010802030151號
購課補貼聯系客服咨詢優惠詳情
慕課網APP您的移動學習伙伴
掃描二維碼關注慕課網微信公眾號
2018-05-09
大神,上面那個是log_process.go的代碼
2018-05-09