httptrace允许跟踪连接何时关闭和/或返回到连接池吗?

huangapple go评论71阅读模式
英文:

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 (
	&quot;io&quot;
	&quot;io/ioutil&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;net/http/httptrace&quot;
	&quot;time&quot;
)

func main() {
	trace := &amp;httptrace.ClientTrace{
		GotConn: func(info httptrace.GotConnInfo) {
			log.Printf(&quot;GotConn(%+v)&quot;, info)
		},
		PutIdleConn: func(err error) {
			log.Printf(&quot;PutIdleConn(%+v)&quot;, err)
		},
	}

	client := http.DefaultClient

	for i := 0; i &lt; 10; i++ {
		req, err := http.NewRequest(&quot;GET&quot;, &quot;https://golang.org/&quot;, 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(&quot;Got response with proto: %s&quot;, res.Proto)

huangapple
  • 本文由 发表于 2021年9月3日 19:52:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/69044478.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定