我正在使用 httptrace.ClientTrace 來跟蹤 Go http 客戶端中發生的各種事件。
它是使用RoundTripper下面的自定義為每個請求完成的。
type TracingRoundTripper struct {
inner http.RoundTripper
mw metrics.WriteAPI
}
func (r *TracingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
var (
host string
dnsStart time.Time
getConn time.Time
connStart time.Time
tlsStart time.Time
)
trace := httptrace.ClientTrace{
DNSStart: func(info httptrace.DNSStartInfo) {
dnsStart = time.Now()
host = info.Host
},
DNSDone: func(info httptrace.DNSDoneInfo) {
if info.Err != nil {
log.Printf("dns error: %v", info.Err)
} else {
r.mw.WritePoint(influxdb2.NewPointWithMeasurement("dns-lookup").AddTag("host", host).AddField("duration", time.Since(dnsStart).Microseconds()))
}
},
GetConn: func(hostPort string) {
getConn = time.Now()
},
GotConn: func(info httptrace.GotConnInfo) {
r.mw.WritePoint(influxdb2.NewPointWithMeasurement("wait-for-conn").AddField("duration", time.Since(getConn).Microseconds()))
if info.WasIdle {
r.mw.WritePoint(influxdb2.NewPointWithMeasurement("conn-idle-reused").AddField("count", 1))
} else if info.Reused {
r.mw.WritePoint(influxdb2.NewPointWithMeasurement("conn-reused").AddField("count", 1))
} else {
r.mw.WritePoint(influxdb2.NewPointWithMeasurement("conn-created").AddField("count", 1))
}
},
PutIdleConn: func(err error) {
r.mw.WritePoint(influxdb2.NewPointWithMeasurement("put-idle-conn").AddField("success", err == nil))
},
ConnectStart: func(network, addr string) {
connStart = time.Now()
},
ConnectDone: func(network, addr string, err error) {
r.mw.WritePoint(influxdb2.NewPointWithMeasurement("conn-handshake").AddField("duration", time.Since(connStart).Microseconds()))
},
TLSHandshakeStart: func() {
tlsStart = time.Now()
},
TLSHandshakeDone: func(s tls.ConnectionState, err error) {
r.mw.WritePoint(influxdb2.NewPointWithMeasurement("tls-handshake").AddField("duration", time.Since(tlsStart).Microseconds()))
},
}
wreq := req.WithContext(httptrace.WithClientTrace(req.Context(), &trace))
return r.inner.RoundTrip(wreq)
}
有趣的是,當我計算寫入的指標事件數時,我觀察到的 DNSDone 事件比 ConnectDone 事件多。只有當我http.Client從多個 go 例程呼叫方法時才會發生這種情況。
我認為假設僅在需要建立新連接時才需要 dns 查找是合理的,那么我們如何解釋上述行為?
非常感謝。
uj5u.com熱心網友回復:
它給出了錯誤的數字,因為我在報告工具中計算了錯誤的事件(GotConn,而不是 ConnectDone)。問題解決了 :-)
uj5u.com熱心網友回復:
我懷疑這是因為連接重用。默認情況下啟用 HTTP 保持活動,因此 TCP 連接將保持打開一段時間,以便可以通過已經打開的 TCP 連接發送第二個 HTTP 請求。因此,DNS 請求將碰巧獲取域的 IP,然后是 IP。如果有一個空閑的 TCP 連接仍然打開到這個 IP,它將被重用,而不是創建一個新的連接(觸發 ConnectDone 事件)。
您應該能夠通過檢查是否ClientTrace.PutIdleConn被呼叫來驗證這一點。您還可以設定Transport.DisableKeepAlives為 true 以禁用保持活動,并且 ConnectDone 事件的數量應該增加(甚至匹配)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/365978.html
標籤:http 走 http-trace
上一篇:將二進制檔案轉換為位元組陣列
