-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
net/http: http.Transport leaks context from the request #50798
Comments
Change https://golang.org/cl/380674 mentions this issue: |
CC @neild |
We seem to be having the same problem. In long running instances, memory utilization is going up every day reaching 80-90% in ~12 days. We started seeing this issue when we upgraded from Go 1.11.3 (no modules) to 1.17 (with go-modules), before the Memory would stay under 30%. Servers have 4GBs. When I run
|
Same issue, there is some news about this? |
In case this helps someone, this other ticket was closed with a comment explaining how to avoid this issue: newrelic/go-agent#447 (comment) |
Well I spotted in my case the solution, I have a global scope context that are aware when a term signal come and all of my workers need to be stopped when it comes. So every time a job start I create a new context with cancel and defer it. With this simple change the leak over bufio.NewWriterSize/bufio.NewReaderSize into transport disappear. |
Any update on this issue? |
my pprof looks exactly the same. are there any workarounds? what can i do? |
…dTrip Clears wannConn ctx and prevents pending dialConnFor after connection delivered or canceled. Fixes golang#50798
Clears wannConn ctx and prevents pending dialConnFor after connection delivered or canceled. Fixes golang#50798
Change https://go.dev/cl/512196 mentions this issue: |
Request context is used to dial connection and there is also #59017 (comment) that suggests that it should not be used for that. |
Clears wannConn ctx and prevents pending dialConnFor after connection delivered or canceled. Updates golang#50798
#61524 only fixes request context leakage but does not fix *persistConn leaks (seen as bufio.NewWriterSize and bufio.NewReaderSize on the pictures) which I plan to address separately. |
Clears wannConn ctx and prevents pending dialConnFor after connection delivered or canceled. Updates #50798 Change-Id: I9a681ac0f222be56571fa768700220f6b5ee0888 GitHub-Last-Rev: fd6c83a GitHub-Pull-Request: #61524 Reviewed-on: https://go-review.googlesource.com/c/go/+/512196 Auto-Submit: Matthew Dempsky <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Reviewed-by: Damien Neil <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
Transport getConn creates wantConn w, tries to obtain idle connection for it based on the w.key and, when there is no idle connection, puts wantConn into idleConnWait wantConnQueue. Then getConn dials connection for w in a goroutine and blocks. After dial succeeds getConn unblocks and returns connection to the caller. At this point w is stored in the idleConnWait and will not be evicted until another wantConn with the same w.key is requested or alive connection returned into the idle pool which may not happen e.g. if server closes the connection. The problem is that even after tryDeliver succeeds w references persistConn wrapper that allocates bufio.Reader and bufio.Writer and prevents them from being garbage collected. To fix the problem this change removes persistConn and error references from wantConn and delivers them via channel to getConn. This way wantConn could be kept in wantConnQueues arbitrary long. Fixes golang#43966 Fixes golang#50798
Transport getConn creates wantConn w, tries to obtain idle connection for it based on the w.key and, when there is no idle connection, puts wantConn into idleConnWait wantConnQueue. Then getConn dials connection for w in a goroutine and blocks. After dial succeeds getConn unblocks and returns connection to the caller. At this point w is stored in the idleConnWait and will not be evicted until another wantConn with the same w.key is requested or alive connection returned into the idle pool which may not happen e.g. if server closes the connection. The problem is that even after tryDeliver succeeds w references persistConn wrapper that allocates bufio.Reader and bufio.Writer and prevents them from being garbage collected. To fix the problem this change removes persistConn and error references from wantConn and delivers them via channel to getConn. This way wantConn could be kept in wantConnQueues arbitrary long. Fixes golang#43966 Fixes golang#50798
Change https://go.dev/cl/522095 mentions this issue: |
Clears wannConn ctx and prevents pending dialConnFor after connection delivered or canceled. Updates golang#50798 Change-Id: I9a681ac0f222be56571fa768700220f6b5ee0888 GitHub-Last-Rev: fd6c83a GitHub-Pull-Request: golang#61524 Reviewed-on: https://go-review.googlesource.com/c/go/+/512196 Auto-Submit: Matthew Dempsky <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Reviewed-by: Damien Neil <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
Transport getConn creates wantConn w, tries to obtain idle connection for it based on the w.key and, when there is no idle connection, puts wantConn into idleConnWait wantConnQueue. Then getConn dials connection for w in a goroutine and blocks. After dial succeeds getConn unblocks and returns connection to the caller. At this point w is stored in the idleConnWait and will not be evicted until another wantConn with the same w.key is requested or alive connection returned into the idle pool which may not happen e.g. if server closes the connection. The problem is that even after tryDeliver succeeds w references persistConn wrapper that allocates bufio.Reader and bufio.Writer and prevents them from being garbage collected. To fix the problem this change removes persistConn and error references from wantConn and delivers them via channel to getConn. This way wantConn could be kept in wantConnQueues arbitrary long. Fixes golang#43966 Fixes golang#50798
I am seemingly still hitting this in 1.23.3, should I open a new issue for this, or should this be reopened? Workaround for this issue is to create a context with a timeout, something like this: ctx, cncl := context.WithTimeout(ctx, time.Second*5)
defer cncl()
req, err := http.NewRequestWithContext(ctx, method, url, bytes.NewBuffer(jsonBytes))
if err != nil {
return nil, err
} |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
I use the
http.Transport
to make an HTTP request. I add a not empty struct in the request context.You can reproduce it like this
What did you expect to see?
After the end of the request, the struct and the context are cleaned by the GC.
What did you see instead?
After the end of the request, the struct and the context are not cleaned by the GC.
Maybe this is the same issue as #43966
The text was updated successfully, but these errors were encountered: