golang HTTP 服務(wù)器 處理 日志/Stream流的操作
目前,我開發(fā) HTTP 服務(wù), 用的是 beego框架, 方便了很多。
但是, 有時(shí)候,還是會(huì)遇到一些 特殊的場(chǎng)景。
比如: 過濾日志。
這應(yīng)該是一種典型的stream,同時(shí)數(shù)據(jù)量也適中, 不會(huì)有人,為了這個(gè), 就用一些很重的框架。
可以這樣直觀的描述這個(gè) 邏輯
其他組件 產(chǎn)生 log
||
\ /
我的組件,業(yè)務(wù)處理
||
\ /
用戶, http client
這種情景下, 有幾個(gè)特殊點(diǎn):
1. 難以用 string,或者 byte 數(shù)組 收集數(shù)據(jù)
2. 數(shù)據(jù)Source 端,不斷的有數(shù)據(jù)產(chǎn)生
3. 數(shù)據(jù)緩沖,如果占有的 內(nèi)存太多, 可能導(dǎo)致 服務(wù)崩潰
通常情況下,我們準(zhǔn)備好數(shù)據(jù), 然后調(diào)用Beego框架的方法,將數(shù)據(jù)發(fā)送到客戶端,就不管了。
而如果,我們需要根據(jù)處理的情況,多次寫數(shù)據(jù)到客戶端,該怎么辦呢?
首先,對(duì)于 這種簡(jiǎn)單的 流數(shù)據(jù), golang 提供了一個(gè) 結(jié)構(gòu)。
pipeReader, pipeWriter := io.Pipe()
這個(gè)方法的原型是這樣的
func Pipe() (*PipeReader, *PipeWriter)
它返回緊密相連的一對(duì) Reader 和 Writer。 他們的“生命周期”相同。
任何 寫到 Writer中的數(shù)據(jù), 直接流到了Reader中。這個(gè) 和 Linux 命令行中 “管道 |” 很像。
我們先開個(gè)goroutine 接收 日志數(shù)據(jù)
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()
總結(jié):
iopipe 直接 對(duì)接了 日志輸出, 緩沖很小,
處理后的結(jié)果, 直接輸出到 http 客戶端。
尤其是第二點(diǎn),很重要,我在處理這個(gè)邏輯的時(shí)候, 發(fā)現(xiàn)服務(wù)器,有幾次意外崩潰,后來(lái),才意識(shí)到,beego的controller 如果緩沖 處理后的數(shù)據(jù),有可能仍然占有大量?jī)?nèi)存。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
Golang服務(wù)的請(qǐng)求調(diào)度的實(shí)現(xiàn)
Golang服務(wù)請(qǐng)求調(diào)度是一種使用Go語(yǔ)言實(shí)現(xiàn)的服務(wù)請(qǐng)求管理方法,本文主要介紹了Golang服務(wù)的請(qǐng)求調(diào)度的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08Golang 類型轉(zhuǎn)換的實(shí)現(xiàn)(斷言、強(qiáng)制、顯式類型)
將一個(gè)值從一種類型轉(zhuǎn)換到另一種類型,便發(fā)生了類型轉(zhuǎn)換,在go可以分為斷言、強(qiáng)制、顯式類型轉(zhuǎn)換,本文就詳細(xì)的介紹一下這就幾種轉(zhuǎn)換方式,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09Go中的格式化字符串fmt.Sprintf()和fmt.Printf()使用示例
這篇文章主要為大家介紹了Go中的格式化字符串fmt.Sprintf()和fmt.Printf()使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06Go語(yǔ)言配置數(shù)據(jù)庫(kù)連接池的實(shí)現(xiàn)
本文內(nèi)容我們將解釋連接池背后是如何工作的,并探索如何配置數(shù)據(jù)庫(kù)能改變或優(yōu)化其性能。文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12部署Go語(yǔ)言項(xiàng)目的 N 種方法(小結(jié))
這篇文章主要介紹了部署Go語(yǔ)言項(xiàng)目的 N 種方法(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11golang 輸出重定向:fmt Log,子進(jìn)程Log,第三方庫(kù)logrus的詳解
這篇文章主要介紹了golang 輸出重定向:fmt Log,子進(jìn)程Log,第三方庫(kù)logrus的詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2020-12-12golang中strconv.ParseInt函數(shù)用法示例
這篇文章主要介紹了golang中strconv.ParseInt函數(shù)用法,實(shí)例分析了strconv.ParseInt函數(shù)將字符串轉(zhuǎn)換為數(shù)字的簡(jiǎn)單使用方法,需要的朋友可以參考下2016-07-07Go處理JSON數(shù)據(jù)的實(shí)現(xiàn)
本文主要介紹了Go處理JSON數(shù)據(jù)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02