Last active
February 8, 2024 03:20
-
-
Save moonsub-kim/6246802d85e16d56609da06af4083065 to your computer and use it in GitHub Desktop.
http connection pool in go explained
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var startTime time.Time | |
trace := &httptrace.ClientTrace { | |
TLSHandshakeStart: func() { | |
startTime = time.Now() | |
}, | |
TLSHandshakeDone: func(s tls.ConnectionState, err error) { | |
fmt.Sprintf("%v elapsed", time.Now() - startTime) | |
}, | |
} | |
traceCtx := httptrace.WithClientTrace(ctx, trace) | |
req := http.Request{ ... } | |
req.WithContext(traceCtx) | |
res, err := client.Do(req) | |
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package httptrace | |
import ( | |
"context" | |
"crypto/tls" | |
"log" | |
"net/http" | |
"net/http/httptrace" | |
"time" | |
) | |
// TransportWithTrace wraps Transport | |
type TransportWithTrace struct { | |
roundtripper http.RoundTripper | |
} | |
// RoundTrip wraps round trip and add traces | |
func (t *TransportWithTrace) RoundTrip(req *http.Request) (res *http.Response, err error) { | |
ctx := t.withTLSTrace(req.Context()) | |
req = req.WithContext(ctx) | |
startTime := time.Now() | |
res, err = t.roundtripper.RoundTrip(req) | |
log.Printf("RoundTrip:: %v elapsed", time.Now() - startTime) | |
} | |
func (t *TransportWithTrace) withTLSTrace(ctx context.Context) context.Context { | |
var startTime time.Time | |
clientTrace := &httptrace.ClientTrace{ | |
TLSHandshakeStart: func() { | |
startTime = time.Now() | |
}, | |
TLSHandshakeDone: func(s tls.ConnectionState, err error) { | |
log.Printf("TLSHandshake:: %v elapsed", time.Now() - startTime) | |
}, | |
} | |
return httptrace.WithClientTrace(ctx, clientTrace) | |
} | |
// WrapRoundTripper returns a new RoundTripper which traces all requests and tls handshakes | |
// sent over the transport. | |
func WrapRoundTripper(roundTripper http.RoundTripper) http.RoundTripper { | |
return &TransportWithTrace{roundTripper, serviceName} | |
} | |
// WrapClient modifies the given client's transport to augment it with tracing and returns it. | |
func WrapClient(c *http.Client) *http.Client { | |
if c.Transport == nil { | |
c.Transport = http.DefaultTransport | |
} | |
c.Transport = WrapRoundTripper(c.Transport) | |
return c | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type ClientTrace struct { | |
GetConn func(hostPort string) | |
GotConn func(GotConnInfo) | |
PutIdleConn func(err error) | |
GotFirstResponseByte func() | |
Got100Continue func() | |
Got1xxResponse func(code int, header textproto.MIMEHeader) error | |
DNSStart func(DNSStartInfo) | |
DNSDone func(DNSDoneInfo) | |
ConnectStart func(network, addr string) | |
ConnectDone func(network, addr string, err error) | |
TLSHandshakeStart func() | |
TLSHandshakeDone func(tls.ConnectionState, error) | |
WroteHeaderField func(key string, value []string) | |
WroteHeaders func() | |
Wait100Continue func() | |
WroteRequest func(WroteRequestInfo) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func main() { | |
c := http.Client{} | |
client = WrapClient(c) | |
req := http.Request{ | |
// fill the required fields | |
} | |
res, err := c.Do(req) | |
if err != nil { | |
... | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
tr := &http.Transport{ | |
MaxIdleConns: 10, | |
} | |
client := &http.Client{Transport: tr} | |
req := http.Request{ | |
// request parameters | |
} | |
resp, err := client.Do(req) | |
if err != nil { | |
// handle error | |
} | |
defer resp.Body.Close() | |
// read response body |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://github.com/golang/go/blob/master/src/net/http/transport.go | |
type Transport struct { | |
// idle connections | |
idleConn map[connectMethodKey][]*persistConn | |
MaxIdleConnsPerHost int | |
IdleConnTimeout time.Duration | |
idleLRU connLRU | |
MaxIdleConns int | |
// wating requests | |
idleConnWait map[connectMethodKey]wantConnQueue | |
connsPerHostWait map[connectMethodKey]wantConnQueue | |
// # of connections | |
connsPerHost map[connectMethodKey]int | |
MaxConnsPerHost int | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I love how you explained transport layer's connection in your article.
It was very helpful, and I really approciate it 😄