英文:
Does httptrace allow to track when a connection is closed and/or returned back to the pool?
问题
我想要在支持HTTP客户端的连接池上捕获一些统计信息。是否可以使用httptrace
包来跟踪连接何时关闭或返回到连接池中?
我有一个虚构的示例(在Go Playground上无法工作,因为涉及到HTTP请求):
package main
import (
"io"
"io/ioutil"
"log"
"net/http"
"net/http/httptrace"
"time"
)
func main() {
trace := &httptrace.ClientTrace{
GotConn: func(info httptrace.GotConnInfo) {
log.Printf("GotConn(%+v)", info)
},
PutIdleConn: func(err error) {
log.Printf("PutIdleConn(%+v)", err)
},
}
client := http.DefaultClient
for i := 0; i < 10; i++ {
req, err := http.NewRequest("GET", "https://golang.org/", nil)
if err != nil {
log.Fatal(err)
}
ctx := httptrace.WithClientTrace(req.Context(), trace)
req = req.WithContext(ctx)
res, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
log.Fatal(err)
}
res.Body.Close()
time.Sleep(10 * time.Millisecond)
}
time.Sleep(1000 * time.Millisecond)
}
运行结果如下:
2021/09/03 13:41:40 GotConn({Conn:0xc00020a000 Reused:false WasIdle:false IdleTime:0s})
2021/09/03 13:41:40 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.389029ms})
2021/09/03 13:41:40 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.305419ms})
2021/09/03 13:41:40 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.874064ms})
2021/09/03 13:41:40 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.303527ms})
2021/09/03 13:41:41 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.815831ms})
2021/09/03 13:41:41 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.679228ms})
2021/09/03 13:41:41 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.580963ms})
2021/09/03 13:41:41 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.95814ms})
2021/09/03 13:41:41 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.788015ms})
问题在于PutIdleConn
从未被调用,尽管我们可以看到连接正在被重用。
我期望当连接被返回到连接池时,PutIdleConn
会被调用,可能会带有错误信息,如果连接池已满,则需要关闭连接。
另外,是否可以使用httptrace
判断连接是否已关闭?
英文:
I want to capture some statistics on the connection pool which backs the http client. Is it possible to track when a connection is closed or returned to the pool using the httptrace
package?
I have this contrived example (doesn't work on go playground because of the http request):
package main
import (
"io"
"io/ioutil"
"log"
"net/http"
"net/http/httptrace"
"time"
)
func main() {
trace := &httptrace.ClientTrace{
GotConn: func(info httptrace.GotConnInfo) {
log.Printf("GotConn(%+v)", info)
},
PutIdleConn: func(err error) {
log.Printf("PutIdleConn(%+v)", err)
},
}
client := http.DefaultClient
for i := 0; i < 10; i++ {
req, err := http.NewRequest("GET", "https://golang.org/", nil)
if err != nil {
log.Fatal(err)
}
ctx := httptrace.WithClientTrace(req.Context(), trace)
req = req.WithContext(ctx)
res, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
log.Fatal(err)
}
res.Body.Close()
time.Sleep(10 * time.Millisecond)
}
time.Sleep(1000 * time.Millisecond)
}
Which prints:
2021/09/03 13:41:40 GotConn({Conn:0xc00020a000 Reused:false WasIdle:false IdleTime:0s})
2021/09/03 13:41:40 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.389029ms})
2021/09/03 13:41:40 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.305419ms})
2021/09/03 13:41:40 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.874064ms})
2021/09/03 13:41:40 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.303527ms})
2021/09/03 13:41:41 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.815831ms})
2021/09/03 13:41:41 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.679228ms})
2021/09/03 13:41:41 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.580963ms})
2021/09/03 13:41:41 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.95814ms})
2021/09/03 13:41:41 GotConn({Conn:0xc00020a000 Reused:true WasIdle:true IdleTime:10.788015ms})
The problem is that PutIdleConn
is never called, even though we can see the connection is being reused.
I've expected that PutIdleConn
will be called when the connection is returned back to the pool, possibly with an error, is the pool is full and then connection needs to be closed.
Related, is it possible to tell that the connection was closed using httptrace
?
答案1
得分: 1
PutIdleConn钩子的文档(针对go 1.17
)表示它目前不适用于HTTP/2,并且对于https://golang.org/
的响应是HTTP/2.0
,可以尝试使用以下代码记录它:
log.Printf("Got response with proto: %s", res.Proto)
英文:
The documentation of PutIdleConn hook for go 1.17
says it's not currently used for HTTP/2, and the response for https://golang.org/
is HTTP/2.0
, try logging it with
log.Printf("Got response with proto: %s", res.Proto)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论