看起来org.springframework.boot.actuate.metrics.web.client.MetricsClientHttpRequestInterceptor
课堂上的这段代码中有错误,第 97 至 99 行:
if (urlTemplate.get().isEmpty()) {
urlTemplate.remove();
}
我认为 if 条件前面应该有一个not运算符,这意味着如果 urlTemplate 线程本地保存的列表不为空,则应该删除项目。
这是在查看代码中的内存泄漏时发现的,这可能是一种极端情况,并且还以某些人认为是滥用的方式使用了 RestTemplate 和 UriTemplateHandler。该问题可以用大致这样的逻辑来重现:
String template = "https://example.org/api/users/{userId}";
for (int i : IntStream.range(0, 10000).toArray()) {
logger.debug("Request to {}", restTemplate.getUriTemplateHandler().expand(template, UUID.randomUUID()));
}
新项目已添加到列表中,但由于缺少not
运算符,因此从未被删除。循环结束后,累积列表可在堆转储中看到。
例如,在处理传入请求时,这似乎不是问题。RestTemplate 在内部使用该机制的方式似乎也没有问题。启用度量执行器并手动使用 UriTemplateHandler.expand() 的长寿命线程是关键。