1. 程式人生 > 程式設計 >golang HTTP 伺服器 處理 日誌/Stream流的操作

golang HTTP 伺服器 處理 日誌/Stream流的操作

目前,我開發 HTTP 服務, 用的是 beego框架, 方便了很多。

但是, 有時候,還是會遇到一些 特殊的場景。

比如: 過濾日誌。

這應該是一種典型的stream,同時資料量也適中, 不會有人,為了這個, 就用一些很重的框架。

可以這樣直觀的描述這個 邏輯

其他元件 產生 log
||
\ /
我的元件,業務處理
||
\ /
使用者, http client

這種情景下, 有幾個特殊點:

1. 難以用 string,或者 byte 陣列 收集資料

2. 資料Source 端,不斷的有資料產生

3. 資料緩衝,如果佔有的 記憶體太多, 可能導致 服務崩潰

通常情況下,我們準備好資料, 然後呼叫Beego框架的方法,將資料傳送到客戶端,就不管了。

而如果,我們需要根據處理的情況,多次寫資料到客戶端,該怎麼辦呢?

首先,對於 這種簡單的 流資料, golang 提供了一個 結構。

pipeReader,pipeWriter := io.Pipe()

這個方法的原型是這樣的

func Pipe() (*PipeReader,*PipeWriter)

它返回緊密相連的一對 Reader 和 Writer。 他們的“生命週期”相同。

任何 寫到 Writer中的資料, 直接流到了Reader中。這個 和 Linux 命令列中 “管道 |” 很像。

我們先開個goroutine 接收 日誌資料

 go func () {
 for {
 var log []byte
 //log = 
 pipeWriter.Write(log)
 
 //break;
 }
 pipeWriter.CloseWithError(io.EOF)
 }

主邏輯中, 處理日誌

 defer pipeReader.Close()
 rr := bufio.NewReader(io.Reader(pipeReader))
 for {

 line,err := rr.ReadBytes('\n')
 if io.EOF == err {
 break
 }
........
 }

最後, 輸出到客戶端

var out []byte
ctl.Ctx.ResponseWriter.Write(out)
ctl.Ctx.ResponseWriter.Flush()

總結:

iopipe 直接 對接了 日誌輸出, 緩衝很小,

處理後的結果, 直接輸出到 http 客戶端。

尤其是第二點,很重要,我在處理這個邏輯的時候, 發現伺服器,有幾次意外崩潰,後來,才意識到,beego的controller 如果緩衝 處理後的資料,有可能仍然佔有大量記憶體。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援我們。如有錯誤或未考慮完全的地方,望不吝賜教。