我有一个 springRest Web 服务端点,它返回一个大小为 4MB 的字符串文本。当我们对此端点进行负载测试时,我们经常看到堆峰值并最终导致系统崩溃。我在想——当我们提出请求时,每个请求都由一个线程单独服务。我的假设是:因为字符串保存在全局静态变量中,所以每个线程获取 4MB 的副本,并且在大约 3000 个请求之后,堆全部被消耗并且系统崩溃,因为每个 4MB 的 3000 个线程大约是 12GB,因此系统内存不足。但这是我的假设。
我的问题:在处理请求的每个线程完成它的工作后,tomcat 不会回收内存吗?这与GC(垃圾收集)有关吗?在请求生命周期中 - 随着请求的到来,创建了一个线程(根据该请求)该线程是获取它自己的响应副本还是仅引用响应?如果将那个巨大的字符串响应复制到每个线程,那么这可能就是显示堆峰值的原因。当响应返回给客户端时,tomcat 如何回收该线程的资源?它什么时候做?是否在声明与 GC 相关的请求线程?
我观察到的另一个方面是:socketWrite0() 方法的延迟——这需要 70-95% 的响应时间。我认为这是一个瓶颈。那么在请求响应的流程中——谁写入套接字?线程?还是线程将响应交给tomcat,然后由tomcat编写?
如果你们中的任何一个可以给我一个提示或一个方面来看看将内存峰值与巨大的字符串响应联系起来,我真的很感激。多谢你们!
玫瑰