一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Golang - 排查 Go 開發的 HttpClient 讀取 Body 超時

排查 Go 開發的 HttpClient 讀取 Body 超時

2022-01-11 01:31精益碼農有態度的馬甲 Golang

本人負責的主備集群,發出的 HttpClient 請求有 30%概率超時, 報context deadline exceeded (Client.Timeout or context cancellation while reading body) 異常

排查 Go 開發的 HttpClient 讀取 Body 超時

記一次go httpclient [讀取響應Body超時]的排查過程。

今年度解鎖的第一個技能。

1故障現場

排查 Go 開發的 HttpClient 讀取 Body 超時

本人負責的主備集群,發出的 HttpClient 請求有 30%概率超時, 報context deadline exceeded (Client.Timeout or context cancellation while reading body) 異常

Kibana 顯示 Nginx 處理請求的耗時request_time在[5s-1min]區間波動, upstream_response_time在 2s 級別。

所以我們認定是 Nginx 向客戶端回傳 50M 的數據,發生了網絡延遲。于是將 HttpClient Timeout 從 30s 調整到 60s, 上線之后明顯改善。

But 昨天又出現了一次同樣的超時異常

  1. time="2022-01-05T22:28:59+08:00" .... 
  2. time="2022-01-05T22:30:02+08:00" level=error msg="service Run error" error="region: sz,first load self allIns error:context deadline exceeded (Client.Timeout or context cancellation while reading body)" 

 2線下復盤

go的HttpClient Timeout包括連接、重定向(如果有)、從Response Body讀取的時間,內置定時器會在Get,Head、Post、Do 方法之后繼續運行,直到讀取完Response.Body.

Timeout specifies a time limit for requests made by this Client. The timeout includes connection time, any redirects, and reading the response body. The timer remains running after Get, Head, Post, or Do return and will interrupt reading of the Response.Body.

Kibana 顯示 Nginx 處理請求的耗時request_time才 32s, 遠不到我們對于 Http 客戶端設置的 60s 超時閾值。

排查 Go 開發的 HttpClient 讀取 Body 超時

這里有必要穿插 Nginx Access Log 的幾個背景點

1.Nginx 寫日志的時間 根據nginx access log[1]官方,NGINX writes information about client requests in the access log right after the request is processed. 也就是說 Nginx 是在端到端請求被處理完之后才寫入日志。

2.Nginx Request_Time upstream_response_time

  • $upstream_response_time – The time between establishing a connection and receiving the last byte of the response body from the upstream server

從 Nginx 向后端建立連接開始到接受完數據然后關閉連接為止的時間

  • $request_time– The total time spent processing a request

Nginx 從接受用戶請求的第一個字節到發送完響應數據的時間

從目前的信息看,Nginx 從接受請求到發送完響應流,總共耗時 32s。那剩下的 28s,是在哪里消耗的?

3三省吾身

這是我抽離的 HttpClient 的實踐, 常規的不能再常規。

  1. package main 
  2.  
  3. import ( 
  4.     "bytes" 
  5.     "encoding/json" 
  6.     "io/ioutil" 
  7.     "log" 
  8.     "net/http" 
  9.     "time" 
  10.  
  11. func main() { 
  12.       c := &http.Client{Timeout: 10 * time.Second
  13.       body := sendRequest(c, http.MethodPost) 
  14.       log.Println("response body length:", len(body)) 
  15.  
  16. func sendRequest(client *http.Client, method string) []byte { 
  17.       endpoint := "http://mdb.qa.17usoft.com/table/instance?method=batch_query" 
  18.       expr := "idc in (logicidc_hd1,logicidc_hd2,officeidc_hd1)" 
  19.       jsonData, err := json.Marshal([]string{expr}) 
  20.       response, err := client.Post(endpoint, "application/json", bytes.NewBuffer(jsonData)) 
  21.       if err != nil { 
  22.           log.Fatalf("Error sending request to api endpoint, %+v", err) 
  23.       } 
  24.       defer response.Body.Close() 
  25.       body, err := ioutil.ReadAll(response.Body) 
  26.       if err != nil { 
  27.           log.Fatalf("Couldn't parse response body, %+v", err) 
  28.       } 
  29.       return body 

核心就兩個動作

  • 調用Get、Post、Do方法發起 Http 請求, 如果無報錯,則表示服務端已經處理了請求
  • iotil.ReadAll表示客戶端準備從網卡讀取 Response Body (流式數據), 超時異常正是從這里爆出來的

報錯內容:"Client.Timeout or context cancellation while reading body" 讀取 Response Body 超時,

潛臺詞是:服務器已經處理了請求,并且開始向客戶端網卡寫入數據。

根據我有限的網絡原理/計算機原理,與此同時,客戶端會異步從網卡讀取 Response Body。

寫入和讀取互不干擾,但是時空有重疊。

排查 Go 開發的 HttpClient 讀取 Body 超時

所以[讀取 Body 超時]位于圖中的紅框區域,這就有點意思了。

  • 之前我們有 30%概率[讀取 Body 超時],確實是因為 Nginx 回傳 50M 數據超時,這在 Nginx request_time 上能體現。
  • 本次 Nginx 顯示 request_time=32s, 卻再次超時,推斷 Nginx 已經寫完數據,而客戶端還沒有讀取完 Body。

至于為什么沒讀取完,這就得吐槽iotil.ReadAll的性能了。客戶端使用 iotil.ReadAll 讀取大的響應體,會不斷申請內存(源碼顯示會從 512B->50M),耗時較長,性能較差、并且有內存泄漏的風險。客戶端機器稍有差池,可能就會導致讀大Body超時, 下一篇我會講解針對大的響應體替換iotil.ReadAll的方案[2]。

為了模擬這個偶發的情況,我們可在Post、iotil.ReadAll前后加入時間日志。

  1. $ go run main.go 
  2. 2022/01/07 20:21:46 開始請求: 2022-01-07 20:21:46.010 
  3. 2022/01/07 20:21:47 服務端處理結束: 2022-01-07 20:21:47.010 
  4. 2022/01/07 20:21:52 客戶端讀取結束: 2022-01-07 20:21:52.010 
  5. 2022/01/07 20:21:52 response body length: 50575756 

可以看出,當讀取大的響應體時候,客戶端iotil.ReadAll的耗時并不算小,這塊需要開發人員重視。

我們甚至可以iotil.ReadAll之前time.Sleep(xxx), 就能輕松模擬出生產環境的讀取 Body 超時。

4我的收獲

1.Nginx Access Log 的時間含義

2.go 的 HttpClient Timeout 包含了連接、請求、讀取 Body 的耗時

3.通過對[讀取 Body 超時異常]的分析,我梳理了端到端的請求耗時、客戶端的行為耗時的時空關系, 這個至關重要。

引用鏈接

[1] nginx access log: https://docs.nginx.com/nginx/admin-guide/monitoring/logging/

[2] 替換iotil.ReadAll的方案: https://stackoverflow.com/questions/52539695/alternative-to-ioutil-readall-in-go

原文鏈接:https://mp.weixin.qq.com/s/gWjnMd26qSbd4vMtEnKSew

延伸 · 閱讀

精彩推薦
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
  • Golanggolang的httpserver優雅重啟方法詳解

    golang的httpserver優雅重啟方法詳解

    這篇文章主要給大家介紹了關于golang的httpserver優雅重啟的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,...

    helight2992020-05-14
  • Golanggolang json.Marshal 特殊html字符被轉義的解決方法

    golang json.Marshal 特殊html字符被轉義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉義的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
  • GolangGolang通脈之數據類型詳情

    Golang通脈之數據類型詳情

    這篇文章主要介紹了Golang通脈之數據類型,在編程語言中標識符就是定義的具有某種意義的詞,比如變量名、常量名、函數名等等,Go語言中標識符允許由...

    4272021-11-24
  • Golanggo日志系統logrus顯示文件和行號的操作

    go日志系統logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統logrus顯示文件和行號的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
  • Golanggolang如何使用struct的tag屬性的詳細介紹

    golang如何使用struct的tag屬性的詳細介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細介紹,從例子說起,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看...

    Go語言中文網11352020-05-21
  • GolangGolang中Bit數組的實現方式

    Golang中Bit數組的實現方式

    這篇文章主要介紹了Golang中Bit數組的實現方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    天易獨尊11682021-06-09
主站蜘蛛池模板: 999久久久 | 色狼屋| 青草社区视频 | 国产日产在线观看 | 国产精品亚洲综合久久 | 色婷婷久久综合中文久久一本 | 色姑娘色综合 | 国产毛片在线高清视频 | 精品国产自在天天线2019 | 国产综合亚洲专区在线 | 国产在线麻豆波多野结衣 | 日韩精品一区二区三区中文在线 | 黑人与欧洲女子性大战 | 日本精品人妖shemale人妖 | 国产卡一卡二卡三卡四 | jm漫天堂破解版 | 四虎永久网址在线观看 | 欧美亚洲天堂网 | 精品国产免费久久久久久婷婷 | 成人榴莲视频 | 草莓香蕉绿巨人丝瓜榴莲污在线观看 | 美女被无套进入 | 福利片免费一区二区三区 | 欧美日韩精品一区二区三区视频在线 | sihu国产午夜精品一区二区三区 | 国产二区精品视频 | 日本破处 | www.俺去啦| 色综合91久久精品中文字幕 | 色综合色综合 | 无码区国产区在线播放 | 国产99青草全福视在线 | 石原莉奈被店长侵犯免费 | 国产成人综合网 | 精品欧美一区二区在线观看欧美熟 | 久久久无码精品亚洲A片猫咪 | 污到你怀疑人生 | 国产男技师 | 性一交一乱一伧老太 | 欧美人与禽杂交大片 | 亚洲AV精品无码喷水直播间 |