大约 3~4 分钟,我的日志中会发生一些错误。
net/http:请求在等待连接时被取消(Client.Timeout 在等待标头时超出)
我尝试使用 httptrace 找出需要时间的地方。httptrace.GetConn httptrace.GotConn
我认为它在 httptrace.GotConn 之前用完了。所以在等待连接时发生错误请求被取消
我的机器没问题,这是我的 netstat。
LAST_ACK 2 CLOSE_WAIT 7 ESTABLISHED 108 SYN_SENT 3 TIME_WAIT 43
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io/ioutil"
"math/rand"
"net"
"net/http"
"net/http/httptrace"
"os"
"sync"
"time"
)
var Client *http.Client = &http.Client{
Transport: &http.Transport{
DisableKeepAlives:true,
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 3 * time.Second, // ????
KeepAlive: 10 * time.Second,
DualStack: true,
}).DialContext,
IdleConnTimeout: 120 * time.Second,
ResponseHeaderTimeout: 60 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
Timeout: 500 * time.Millisecond,
}
func GenLogId() string {
h2 := md5.New()
rand.Seed(time.Now().Unix())
str := fmt.Sprintf("%d%d%d", os.Getpid(), time.Now().UnixNano(), rand.Int())
h2.Write([]byte(str))
uniqid := hex.EncodeToString(h2.Sum(nil))
return uniqid
}
func main() {
var (
wg sync.WaitGroup
maxParallel int = 50
parallelChan chan bool = make(chan bool, maxParallel)
)
for {
parallelChan <- true
wg.Add(1)
go func() {
defer func() {
wg.Done()
<-parallelChan
}()
testHttp2()
}()
}
wg.Wait()
}
func testHttp2() {
url := "http://10.33.108.39:11222/index.php"
req, _ := http.NewRequest("GET", url, nil)
uniqId := GenLogId()
trace := &httptrace.ClientTrace{
GetConn: func(hostPort string) {
fmt.Println("GetConn id:", uniqId, time.Now().UnixNano(), hostPort)
},
GotConn: func(connInfo httptrace.GotConnInfo) {
fmt.Println("GotConn id:", uniqId, time.Now().UnixNano(), connInfo.Conn.LocalAddr())
},
ConnectStart: func(network, addr string) {
fmt.Println("ConnectStart id:", uniqId, time.Now().UnixNano(), network, addr)
},
ConnectDone: func(network, addr string, err error) {
fmt.Println("ConnectDone id:", uniqId, time.Now().UnixNano(), network, addr, err)
},
}
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
resp, err := Client.Do(req)
if err != nil {
fmt.Println("err: id", uniqId, time.Now().UnixNano(), err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("error", string(body))
}
return
}
Run Code Online (Sandbox Code Playgroud)
您可以使用我的代码进行复制。我对这个错误很困惑……谢谢。
was*_*mup 12
您需要为您的测试增加客户端Timeout值。
net/http: request canceled (Client.Timeout exceeded while awaiting headers)
这意味着您的Client.Timeout值小于您的服务器响应时间,原因有很多(例如,繁忙、CPU 过载、您在此处生成的每秒许多请求,...)。
这里有一个简单的方法来解释它并重新生成它:
运行此服务器(等待2 * time.Second然后发回响应):
package main
import (
"io"
"log"
"net/http"
"time"
)
func main() {
http.HandleFunc(`/`, func(w http.ResponseWriter, r *http.Request) {
log.Println("wait a couple of seconds ...")
time.Sleep(2 * time.Second)
io.WriteString(w, `Hi`)
log.Println("Done.")
})
log.Println(http.ListenAndServe(":8080", nil))
}
Run Code Online (Sandbox Code Playgroud)
然后运行这个超时的客户端1 * time.Second:
package main
import (
"io/ioutil"
"log"
"net/http"
"time"
)
func main() {
log.Println("HTTP GET")
client := &http.Client{
Timeout: 1 * time.Second,
}
r, err := client.Get(`http://127.0.0.1:8080/`)
if err != nil {
log.Fatal(err)
}
defer r.Body.Close()
bs, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Fatal(err)
}
log.Println("HTTP Done.")
log.Println(string(bs))
}
Run Code Online (Sandbox Code Playgroud)
输出为 ( Client.Timeout exceeded while awaiting headers):
2019/10/30 11:05:08 HTTP GET
2019/10/30 11:05:09 Get http://127.0.0.1:8080/: net/http: request canceled (Client.Timeout exceeded while awaiting headers)
exit status 1
Run Code Online (Sandbox Code Playgroud)
注意:
您需要相应地更改这两个设置(http.Transport.ResponseHeaderTimeout和http.Client.Timeout)。
您已将ResponseHeaderTimeout: 60 * time.Second,while设置Client.Timeout为半秒。
| 归档时间: |
|
| 查看次数: |
23275 次 |
| 最近记录: |