HTTP客户端挂起

时间:2015-08-04 06:40:15

标签: 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) 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)

没有什么不寻常的。但过了一段时间后,我得到了这些goroutines建立起来并且只是阻塞,这是一个恐慌之后得到追踪的例子:

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

goroutine 418 [IO wait, 4 minutes]:
net.(*pollDesc).Wait(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_poll_runtime.go:89 +0x43
net.(*netFD).Read(0xc2083c7810, 0xc20857e000, 0x1000, 0x1000, 0x0, 0x7fbb634c3bb0, 0xc2084d87a0)
    /usr/local/go/src/net/fd_unix.go:242 +0x40f
net.(*conn).Read(0xc208116020, 0xc20857e000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
    /usr/local/go/src/net/net.go:121 +0xdc
net/http.noteEOFReader.Read(0x7fbb634c7288, 0xc208116020, 0xc208075b28, 0xc20857e000, 0x1000, 0x1000, 0x678100, 0x0, 0x0)
    /usr/local/go/src/net/http/transport.go:1270 +0x6e
net/http.(*noteEOFReader).Read(0xc2083d84c0, 0xc20857e000, 0x1000, 0x1000, 0xc208017600, 0x0, 0x0)
    <autogenerated>:125 +0xd4
bufio.(*Reader).fill(0xc20858c0c0)
    /usr/local/go/src/bufio/bufio.go:97 +0x1ce
bufio.(*Reader).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
created by net/http.(*Transport).dialConn
    /usr/local/go/src/net/http/transport.go:660 +0xc9f

我一直在尝试观看netstattcpdump,看看他们实际上遇到了什么,但它现在并没有证明非常有用。在进入源头或对我的监控更加勤奋之前,我想我会把这个问题抛到脑后。这是怎么回事?..

为什么我的超时不起作用?我需要设置另一个超时吗? (正如你所看到的那样,我只是继续设置我能找到的每一个,还有响应标头超时,也许我应该设置它?我认为http.Client结构中的超时非常稳定,但会超时)

最后,有没有办法设置我缺少的客户端端口,以便我可以更好地监控哪些连接有问题?

编辑:为了记录,我也很确定我正在阅读/关闭每个请求的响应正文。除非有些东西在某种程度上悬挂在超时或我不知道的东西上,但如果这是别人看到的唯一解决方案,我会再次看。

1 个答案:

答案 0 :(得分:0)

原来这些不是问题,它们似乎只是保持活着的消息(虽然奇怪的是我设置了KeepAlive: 0?)。错误Done() sync.WaitGroup上的错误是真正的罪魁祸首。我想我开始查看Wait()而不是http.Client调用的每个sync.WaitGroup