万博manbetx官方app_万博手机客户端安卓版_万博手机-Nginx 从收受请求到发送完反馈流
Nginx 从收受请求到发送完反馈流
发布日期:2022-02-16 14:07    点击次数:211

Nginx 从收受请求到发送完反馈流

万博manbetx官方app_万博手机客户端安卓版_万博手机版max

记一次go httpclient [读取反馈Body超时]的排查经由。

本年度解锁的第一个手段。

1故障现场

本身肃肃的主备集群,发出的 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 昨天又出现了一次通常的超时终点

time="2022-01-05T22:28:59+08:00" 万博manbetx官方app_万博手机客户端安卓版_万博手机版max.... 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 超时阈值。

这里有必要穿插 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 的试验, 惯例的不行再惯例。

package main  import (     "bytes"     "encoding/json"     "io/ioutil"     "log"     "net/http"     "time" )  func main() {       c := &http.Client{Timeout: 10 * time.Second}       body := sendRequest(c, http.MethodPost)       log.Println("response body length:", len(body)) }  func sendRequest(client *http.Client, method string) []byte {       endpoint := "http://mdb.qa.17usoft.com/table/instance?method=batch_query"       expr := "idc in (logicidc_hd1,logicidc_hd2,officeidc_hd1)"       jsonData, err := json.Marshal([]string{expr})       response, err := client.Post(endpoint, "application/json", bytes.NewBuffer(jsonData))       if err != nil {           log.Fatalf("Error sending request to api endpoint, %+v", err)       }       defer response.Body.Close()       body, err := ioutil.ReadAll(response.Body)       if err != nil {           log.Fatalf("Couldn't parse response body, %+v", err)       }       return body } 

中枢就两个行为

万博manbetx官方app_万博手机客户端安卓版_万博手机版max平台客服QQ:865083652 调用Get、Post、Do圭臬发起 Http 请求, 若是无报错,则示意管事端也曾解决了请求 iotil.ReadAll示意客户端准备从网卡读取 Response Body (流式数据), 超时终点恰是从这里爆出来的

报错实质:"Client.Timeout or context cancellation while reading body" 读取 Response Body 超时,

潜台词是:管事器也曾解决了请求,况且运转向客户端网卡写入数据。

左证我有限的网罗旨趣/筹办机旨趣,与此同期,客户端会异步从网卡读取 Response Body。

int a = 1; int b = 2; int temp; temp = a; a = b; b = temp; 

简洁优雅的 Python 写法:

我们继续往下看,大名鼎鼎的进程调度初始化,shed_init。

写入和读取互不搅扰,然而时空有重复。

是以[读取 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前后加入时分日记。

$ go run main.go 2022/01/07 20:21:46 运转请求: 2022-01-07 20:21:46.010 2022/01/07 20:21:47 管事端解决收尾: 2022-01-07 20:21:47.010 2022/01/07 20:21:52 客户端读取收尾: 2022-01-07 20:21:52.010 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

 



  • 上一篇:没有了
  • 下一篇:不错骄气L4级别的自动驾驶运算需求