-
Notifications
You must be signed in to change notification settings - Fork 40.9k
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
Potential memory leak in MetricsClientHttpRequestInterceptor #25860
Comments
Thanks for the report. The behaviour that you have observed is a side-effect of the fix for #19381. The I'm not sure what we should do about this. bf6f36a has introduced |
Thanks for the comment. If I can suggest, removing those lines 97 - 99 should at least remove the confusion about the condition's correctness, if the code otherwise is working as planned. In my case it's likely the usage for logging, which could lead to bypassing something that would otherwise be done. The condition however caught my eye. |
I don't think those lines should be removed as it will make things slightly worse. If they were removed, the thread local would be left holding onto an empty |
You're right, after a closer look at the previous issue #19381 the current implementation makes sense. I'll leave this open if you want to discuss it more, but it seems to me the "borrowing" of the UriTemplateHandler for manual template expansion was probably just a bit too clever for you own good type of solution. |
@mbechtold1, with reference to #26853, how are you using the URL template handler? |
Hope this is what you're asking for... String url = UriComponentsBuilder.fromUriString(template).buildAndExpand(params).toUriString();
RestTemplate.exchange(url, HttpMethod.GET, requestEntity, Void.class); I've seen another instance using... RestTemplate.exchange(url, HttpMethod.GET, requestEntity, Void.class, variables); |
That style of usage shouldn't cause a problem. URL templates are pushed onto the If you believe you're seeing behaviour that's contrary to what I've described above it'd be great if you could provide a sample project that reproduces it so that we can investigate further. |
projects.zip |
Thanks very much, @mbechtold1. That sample has allowed me to identify a different problem. In your case, auto-timing is disabled so |
Sorry I struggle with the code. I just tried to put something together quickly. Please feel free to correctly update my configuration. |
The problem's in your
I've made two changes:
|
Thanks Andy. I appreciate your help. |
We upgraded our application to
Correct ways:
Posting for future users who might face the same issue. |
I don't think we're going to be able to close this issue in the 2.x line without breaking other use cases. This all comes from the fact that I'm closing in favor of spring-projects/spring-framework#28341 |
A memory leak is still present in Spring Boot 2.7.18 due to logic in
One potential solution to mitigate issue is to use a fixed size evicting deque that will store only up to N latest items, e.g. N = 100. If size exceeds the limit for such deque, it will evict old items from the head of the deque. I can't imagine when someone needs to invoke from interceptor more than N=100 additional nested requests by a single initial API request. Even if it is exceeded, logic could generate metrics only by N nested requests and skip others. What do you think about this proposal? If the idea is accepted, I could contribute such fix. |
Thanks for the offer @vasiliy-sarzhynskyi but 2.7.x has reached end of OSS support. Please upgrade your application to a supported version of Spring Boot. |
Looks like there's a bug in this code in
org.springframework.boot.actuate.metrics.web.client.MetricsClientHttpRequestInterceptor
class, lines 97 - 99:I believe the if condition should have a not operator in front of it, meaning item(s) should be removed if the list held by urlTemplate thread-local is not empty.
This came up when looking at a memory leak in code, which is likely an edge case and also uses RestTemplate and UriTemplateHandler in a way some could characterize as misuse. The problem can be reproduced with roughly this kind of logic:
New items are added to the list, but never removed due to the missing
not
operator. The accumulated list is visible in heap dump after that loop has finished.This doesn't seem to be an issue for example in handling of incoming requests. It also looks like there's no problem in how RestTemplate uses the mechanism internally. Long-lived thread with manual UriTemplateHandler.expand() usage with metrics actuator enabled is the key.
The text was updated successfully, but these errors were encountered: