Go HTTP客户端挂起
我有一些代码可以生成大量简单的HTTP GET请求 我使用的客户端设置如下:Go HTTP客户端挂起,go,Go,我有一些代码可以生成大量简单的HTTP GET请求 我使用的客户端设置如下: type client struct { *http.Client // other stuff in here } func NewClient() client { var c client c.Client = &http.Client{ CheckRedirect: func(req *http.Request, via []*http.Request)
type client struct {
*http.Client
// other stuff in here
}
func NewClient() client {
var c client
c.Client = &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
req.Header.Set("User-Agent", c.userAgent)
return nil
},
Transport: &http.Transport{
Dial: func(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, 2*time.Second)
},
TLSHandshakeTimeout: 2 * time.Second,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
Timeout: 2 * time.Second,
}
return c
}
req, err := http.NewRequest("GET", url, nil)
正如你所看到的,我真的在努力确保我的坏连接超时。我提出如下要求:
type client struct {
*http.Client
// other stuff in here
}
func NewClient() client {
var c client
c.Client = &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
req.Header.Set("User-Agent", c.userAgent)
return nil
},
Transport: &http.Transport{
Dial: func(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, 2*time.Second)
},
TLSHandshakeTimeout: 2 * time.Second,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
Timeout: 2 * time.Second,
}
return c
}
req, err := http.NewRequest("GET", url, nil)
那里没有什么不寻常的事。但过了一段时间,我发现这些goroutine正在构建并阻塞,这是一个在恐慌之后获取跟踪的示例:
goroutine 325 [select, 4 minutes]:
net/http.(*persistConn).writeLoop(0xc208075130)
/usr/local/go/src/net/http/transport.go:945 +0x41d
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:661 +0xcbc
及
goroutine418[IO等待,4分钟]:
net。(*pollDesc)。等待(0xc2083c7870、0x72、0x0、0x0)
/usr/local/go/src/net/fd_poll_runtime.go:84+0x47
net(*pollDesc).WaitRead(0xc2083c7870,0x0,0x0)
/usr/local/go/src/net/fd\u poll\u运行时。go:89+0x43
读取(0xc2083c7810、0xc20857e000、0x1000、0x1000、0x0、0x7FBB634C3B0、0xc2084d87a0)
/usr/local/go/src/net/fd_unix.go:242+0x40f
读取(0xc208116020、0xc20857e000、0x1000、0x1000、0x0、0x0、0x0)
/usr/local/go/src/net/net.go:121+0xdc
net/http.NoteofReader.Read(0x7fbb634c7288、0xc208116020、0xc208075b28、0xc20857e000、0x1000、0x1000、0x678100、0x0、0x0)
/usr/local/go/src/net/http/transport.go:1270+0x6e
net/http。(*NoteoFreader).Read(0xc2083d84c0,0xc20857e000,0x1000,0xc208017600,0x0,0x0)
:125+0xd4
bufio.(*读卡器).填充(0xc20858c0c0)
/usr/local/go/src/bufio/bufio.go:97+0x1ce
bufio.(*读卡器).Peek(0xc20858c0c0,0x1,0x0,0x0,0x0,0x0,0x0)
/usr/local/go/src/bufio/bufio.go:132+0xf0
net/http。(*persistConn).readLoop(0xc208075ad0)
/usr/local/go/src/net/http/transport.go:842+0xa4
由网络/http创建。(*传输)。拨号连接
/usr/local/go/src/net/http/transport.go:660+0xc9f
我一直在尝试观看netstat
和tcpdump
,看看他们到底在做什么,但现在证明它不是很有用。在深入到源代码或更加认真地监控之前,我想我会把这个问题抛到一边。这是怎么回事
还有,为什么我的超时不起作用?是否需要设置另一个超时?(正如您所看到的,我一直在设置我能找到的每一个响应头超时,可能我也应该设置响应头超时?我认为http.Client结构中的超时非常可靠,可以超时任何内容)
最后,有没有办法设置我丢失的客户端端口,以便更好地监视哪些连接出现问题
编辑:作为记录,我也非常确定我正在阅读/关闭每个请求的响应主体。除非有一些消息因超时或我不知道的原因而挂起,但如果这是唯一的解决方案,我会再次查看。结果表明,这不是问题所在,它们似乎只是保持活动的消息(尽管奇怪的是,我设置了
KeepAlive:0
集?)。将Done()
放错sync上。WaitGroup
才是真正的罪魁祸首。我想我开始把每个Wait()
看作是被http.Client
调用的,而不是sync.WaitGroup
也许这个问题的答案可能会有所帮助。嗯,我不知道,除了确保你读了整件事之外,这个问题似乎没有结论,实际上,我使用的方法是,在调用Close()
之前,answer指定io.Copy(ioutil.Discard,r.Body)
,只是为了确定它是可读的,你的程序是否在某个地方被阻塞了?这看起来像是“保持活力”的连接。我刚刚注意到现在。。。看起来问题实际上可能出在sync.WaitGroup
;)我假设当你说你有KeepAlive:0
,你指的是网络拨号程序中的设置,因为在http中没有类似的设置。这是针对tcp keepalive的,它与http keepalive完全不同,http keepalive只是可以重用的连接。哦,谢谢你,我不知道,我是指拨号程序。