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

Limit concurrent S3 connections per host #186

Closed
wants to merge 1 commit into from

Conversation

JensErat
Copy link

This commit limits the number of concurrent connections to encourage
connection reuse. MaxIdleConnsPerHost was already set to workaround
golang/go#13801 ("issue which made Go consume
all ephemeral ports").

We observed a similar issue when starting up Loki (using weaveworks
common/aws throught Cortex) which resulted in thousands of very small
S3 requests until memcached was seeded. This failed because of ephemeral
port exhaustion: while the application in fact would have reused
connections, it already failed as it sent all of them concurrently until
most of the requests failed.

MaxConnsPerHost can be used to limit the overall number of parallel
connections.

An alternative solution would be to queue requests in the application, but the golang HTTP client already has a queue. Whether a maximum of 100 parallel requests is reasonable or too small might be subject of discussion. I'm not sure if there is a relevant use case of more than 100 parallel S3 streams per instance.

In my experiments, a connection limit larger than MaxIdleConns resulted in few connections piling up, but in a rate the system could handle well (with other words: they went through their TIME_WAIT window and were removed from the connection list without the system getting close to the ephemeral connection limit).

This commit limits the number of concurrent connections to encourage
connection reuse. `MaxIdleConnsPerHost` was already set to workaround
golang/go#13801 ("issue which made Go consume
all ephemeral ports").

We observed a similar issue when starting up Loki (using weaveworks
`common/aws` throught Cortex) which resulted in thousands of very small
S3 requests until memcached was seeded. This failed because of ephemeral
port exhaustion: while the application in fact would have reused
connections, it already failed as it sent all of them concurrently until
most of the requests failed.

`MaxConnsPerHost` can be used to limit the overall number of parallel
connections.
@bboreham
Copy link
Collaborator

This code is used for more than S3. Given that it is a highly-reused library I would prefer to see parallelism limited at source, rather than deep in the SDK code.

Worst case the limit should be configurable, off by default, and commented.

@JensErat
Copy link
Author

As already mentioned, I'm not really sure this is an all-valid default. Making it configurable would make a bunch of use cases much easier, though. Sadly, modifying the HTTP client's from outside the function seems not really possible (or I was just lost in a hell of type assertions). Optionally passing an HTTP client or transport might be somewhat feasible though.

As already discussed in the Loki issue, Loki/Cortex already implemented an improved schema some months ago (which was the new recommended one just few days after we digged into the issue). So on the client-side, there definitely is some improvement works.

When reading through this comment again I have the feeling one of those two occurrences of MaxIdleConnsPerHost should actually be MaxIdleConns?

// Use a custom http.Client with the golang defaults but also specifying
// MaxIdleConnsPerHost because of a bug in golang https://github.com/golang/go/issues/13801
// where MaxIdleConnsPerHost does not work as expected.

@bboreham
Copy link
Collaborator

one of those two occurrences of MaxIdleConnsPerHost should actually be MaxIdleConns?

Assuming you mean "one of those two occurrences in the comment", I don't think so. The struct is copy-pasted from the Go DefaultTransport, plus a line specifying MaxIdleConnsPerHost, because (reason).

@bboreham
Copy link
Collaborator

bboreham commented Aug 4, 2020

@JensErat are you planning to come back to this?

@bboreham bboreham closed this Aug 20, 2020
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

Successfully merging this pull request may close these issues.

2 participants