[golang]為什么Response.Body需要被關(guān)閉

Body io.ReadCloser

The http Client and Transport guarantee that Body is always non-nil, even on 
responses without a body or responses with a zero-length body. It is the caller's 
responsibility to close Body. The default HTTP client's Transport does not attempt to 
reuse HTTP/1.0 or HTTP/1.1 TCP connections ("keep-alive") unless the Body is read to 
completion and is closed.

http客戶端(Client)和傳輸(Transport)保證響應(yīng)體總是非空的,即使響應(yīng)沒有響應(yīng)體或0長響應(yīng)
體瞒大。關(guān)閉響應(yīng)體是調(diào)用者的責(zé)任系洛。默認(rèn)http客戶端傳輸(Transport)不會嘗試復(fù)用keep-alive的
http/1.0俊性、http/1.1連接,除非請求體已被完全讀出而且被關(guān)閉了描扯。

以上是http包文檔說明磅废。但是為什么body需要被關(guān)閉呢,不關(guān)閉會如何荆烈?那就讀源碼唄。

要了解body竟趾,首先要了解http事務(wù)是如何處理的憔购。http事務(wù)是交由底層的Transport處理的。

第一步是從連接池獲取一個連接岔帽,這個連接的功能由3個goroutine協(xié)同實現(xiàn)玫鸟,一個主goroutine,一個readLoop犀勒,一個writeLoop屎飘,后兩個goroutine生命周期和連接一致。雖說readLoop和writeLoop名字叫循環(huán)(也確實是for循環(huán))贾费,但實際上一次循環(huán)就完整處理一個http事務(wù)钦购,循環(huán)本身僅僅是為了連接復(fù)用,所以為了便于理解其邏輯可以忽略它的循環(huán)結(jié)構(gòu)褂萧。

接下來三個goroutine協(xié)同完成http事務(wù):

  1. 主goroutine將request同時發(fā)給readLoop和writeLoop押桃。
  2. writeLoop發(fā)送request,然后將狀態(tài)(error)發(fā)送給主goroutine和readLoop导犹。
  3. readLoop解析頭部response唱凯,然后將狀態(tài)(error)和response發(fā)送給主goroutine。
  4. 主goroutine返回用戶代碼谎痢,readLoop等待body讀取完成磕昼。
  5. readLoop回收連接。

了解http事務(wù)的處理流程节猿,然后我們回過頭來看看神秘的body到底是什么

//源碼版本1.8.3
// src/net/http/transfer.go:405 body解析方法
func readTransfer(msg interface{}, r *bufio.Reader) (err error)

// src/net/http/transfer.go:485 解析chunked
t.Body = &body{src: internal.NewChunkedReader(r), hdr: msg, r: r, closing: t.Close}

// src/net/http/transfer.go:490 產(chǎn)生eof
t.Body = &body{src: io.LimitReader(r, realLength), closing: t.Close}

// src/net/http/transport.go:1560 發(fā)送eof信號
body := &bodyEOFSignal{

// src/net/http/transport.go:1583 gzip解碼
resp.Body = &gzipReader{body: body}

body實際上是一個嵌套了多層的net.TCPConn:

  1. bufio.Reader票从,這層嘗試將多次小的讀操作替換為一次大的讀操作,減少系統(tǒng)調(diào)用的次數(shù),提高性能纫骑;
  2. io.LimitedReader蝎亚,tcp連接在讀取完body后不會關(guān)閉,繼續(xù)讀會導(dǎo)致阻塞先馆,所以需要LimitedReader在body讀完后發(fā)出eof終止讀确⒖颉;
  3. chunkedReader煤墙,解析chunked格式編碼(如果不是chunked略過)梅惯;
  4. bodyEOFSignal,在讀到eof仿野,或者是提前關(guān)閉body時會對readLoop發(fā)出回收連接的通知铣减;
  5. gzipReader,解析gzip壓縮(如果不是gizp壓縮略過)脚作;

從上面可以看出如果body既沒有被完全讀取葫哗,也沒有被關(guān)閉,那么這次http事務(wù)就沒有完成球涛,除非連接因超時終止了劣针,否則相關(guān)資源無法被回收。

如果請求頭或響應(yīng)頭指明Connection: close呢亿扁?還是無法回收捺典,因為close表示在http事務(wù)完成后斷開連接,而事務(wù)尚未完成自然不會斷開从祝,更不會回收襟己。

從實現(xiàn)上看只要body被讀完,連接就能被回收牍陌,只有需要拋棄body時才需要close擎浴,似乎不關(guān)閉也可以。但那些正常情況能讀完的body毒涧,即第一種情況退客,在出現(xiàn)錯誤時就不會被讀完,即轉(zhuǎn)為第二種情況链嘀。而分情況處理則增加了維護(hù)者的心智負(fù)擔(dān)萌狂,所以始終close body是最佳選擇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怀泊,一起剝皮案震驚了整個濱河市茫藏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌霹琼,老刑警劉巖务傲,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凉当,死亡現(xiàn)場離奇詭異,居然都是意外死亡售葡,警方通過查閱死者的電腦和手機看杭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挟伙,“玉大人楼雹,你說我怎么就攤上這事〖饫” “怎么了贮缅?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長介却。 經(jīng)常有香客問我谴供,道長,這世上最難降的妖魔是什么齿坷? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任桂肌,我火速辦了婚禮,結(jié)果婚禮上永淌,老公的妹妹穿的比我還像新娘崎场。我一直安慰自己,他們只是感情好仰禀,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蚕愤,像睡著了一般答恶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上萍诱,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天悬嗓,我揣著相機與錄音,去河邊找鬼裕坊。 笑死包竹,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的籍凝。 我是一名探鬼主播周瞎,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼饵蒂!你這毒婦竟也來了声诸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤退盯,失蹤者是張志新(化名)和其女友劉穎彼乌,沒想到半個月后泻肯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡慰照,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年灶挟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毒租。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡稚铣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蝌衔,到底是詐尸還是另有隱情榛泛,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布噩斟,位于F島的核電站曹锨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏剃允。R本人自食惡果不足惜沛简,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斥废。 院中可真熱鬧椒楣,春花似錦、人聲如沸牡肉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽统锤。三九已至毛俏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饲窿,已是汗流浹背煌寇。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留逾雄,地道東北人阀溶。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像鸦泳,于是被迫代替她去往敵國和親银锻。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理做鹰,服務(wù)發(fā)現(xiàn)徒仓,斷路器,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • 第一章 Nginx簡介 Nginx是什么 沒有聽過Nginx誊垢?那么一定聽過它的“同行”Apache吧掉弛!Ngi...
    JokerW閱讀 32,646評論 24 1,002
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法症见,類相關(guān)的語法,內(nèi)部類的語法殃饿,繼承相關(guān)的語法谋作,異常的語法,線程的語...
    子非魚_t_閱讀 31,597評論 18 399
  • 從三月份找實習(xí)到現(xiàn)在乎芳,面了一些公司遵蚜,掛了不少,但最終還是拿到小米奈惑、百度吭净、阿里、京東肴甸、新浪寂殉、CVTE、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,207評論 11 349
  • 接第四章百里杜鵑 花間初見 第五章 江南雨濃 雨后天已放晴原在,窗外的芭蕉葉兒格外的綠友扰,那碩大的葉片上還淌著幾滴未落欲...
    丁漁閱讀 679評論 2 3