Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raise the rpc client's MaxIdleConnsPerHost #19

Open
WhoSoup opened this issue Jan 6, 2020 · 0 comments
Open

Raise the rpc client's MaxIdleConnsPerHost #19

WhoSoup opened this issue Jan 6, 2020 · 0 comments

Comments

@WhoSoup
Copy link
Contributor

WhoSoup commented Jan 6, 2020

This was an edge case I came across while hammering an endpoint with requests. By default, the golang http client reuses connections but it only has a limited capacity for how many "waiting" connections it can hold. That number is defined by "MaxIdleConnsPerHost" and the default is 2. If more than 2 connections to the same host (protocol+hostname+port) are given back to the Transport object, the oldest connection will be closed.

I was using 8 goroutines and I consistently ran into an issue where I ran out of local dynamic ports (windows). The TLDR is that the OS doesn't immediately free up the resources of this closed connection but rather takes about 2 minutes (windows' TcpTimedWaitDelay). These app-closed but os-pending connections keep building up faster than being returned to the pool.

If the Transport.MaxIddleConnsPerHost value is raised to a more reasonable value, this will improve the use of finite system resources. Pegnetd uses 8 goroutines and FAT/factom uses NumCPU() goroutines, so I was thinking something along the lines of 32 or 64 as default value.

Code snippet (apart from MaxIdleConnsPerHost this is just a copy/paste of the DefaultTransport):

	cli := factom.NewClient()
	cli.FactomdServer = "http://localhost:8088/v2"
	tpp := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
			DualStack: true,
		}).DialContext,
		ForceAttemptHTTP2:     true,
		MaxIdleConns:          100,
		MaxIdleConnsPerHost:   32,
		IdleConnTimeout:       90 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	}
	cli.Factomd.Transport = tpp

This allowed me to reuse one connection for each goroutine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant