java - 内存泄漏问题 org.apache.tomcat.util.collections.SynchronizedStack 类
问题描述
我们对我们的 Spring Boot 文件下载应用程序进行了负载测试,加载了 4000 个并发用户,其中 3995 个成功,其中 5 个失败。
我们下载的文件是1 MB
每个请求的。
我们在负载测试结束时使用了堆转储
jcmd pid GC.heap_dump <filename>
分析堆转储后,我意识到tomcat的 org.apache.tomcat.util.collections.SynchronizedStack<org.apache.tomcat.util.net.NioChannel> 没有被释放。我们已经对 500、700 和 4000 的多个用户负载进行了测试。这个特定的对象在内存中不断增加,但没有释放任何东西。
这是我在 application.properties 中的 tomcat 配置
server.tomcat.connection-timeout=20s
server.tomcat.accept-count=5000
server.tomcat.max-connections=50000
server.tomcat.max-threads=10000
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
我是否在我的 tomcat 配置中缺少任何用于 Spring Boot 的内容?
应用程序堆栈:Open JDK 11 上的 spring boot 2.2.0.RELEASE。
我们用于文件下载的一些代码:
@GetMapping(path = "/file/download/{downloadToken}")
@ApiOperation(value = "downloadFile", authorizations = {@Authorization(value = "apiKey")})
public StreamingResponseBody downloadFile(@PathVariable String downloadToken,
HttpServletResponse response) {
MyFileObject myFileObject = myFileService.downloadFile(downloadToken);
response.setContentType(myFileObject.getContentType());
response.setHeader("Content-Disposition",
"attachment; filename=\"" + myFileObject.getFileName() + "\"");
return out -> {
try (OutputStream os = out) {
os.write(myFileObject.getData());
}
};
}
作为 DTO 的 MyFileObject
@Getter
@Setter
@AllArgsConstructor
@ToString
class MyFileObject {
private String fileName;
private String contentType;
private byte[] data;
}
注意:由于其他业务原因,我们在内存中有整个 byte[] 数据(1 MB)。但是,根据堆转储,这不是泄漏的原因,因为这些对象是 GCed。
来自堆转储的 MAT 工具的一些屏幕截图
解决方案
推荐阅读
- python - 是否可以在 Kivy 中使用多个 ScreenManager 小部件?
- javascript - 如何避免 RegExp 中的灾难性回溯?
- java - 如何在 JAVA 中使用 HTTP Patch 将增量行修补到文件?
- autodesk-forge - 模型导数教程文件丢失
- javascript - 阻止在输入类型号中输入负值的角度方式(在复制粘贴和增加、减少时)
- c# - 从 EventHandler void 返回一个字符串值
- java - Thymeleaf 页面未重定向到另一个页面
- three.js - Three.js片段着色器颜色过渡
- python - odoo框架中的ORM
- firebase - 如何在firebase firestore中存储关键字