Spring集成测试消耗大量内存,在GradleWorkerMain中使用大量重复线程

Eri*_*vic 9 java spring spring-boot

我有一个有点复杂的Spring Boot应用程序,有大量的测试.

在运行测试时,它似乎正在积累很多线程,其中一个线程有多个并且被调用SimplePauseDetectorThread_0,我追溯到这个依赖项

|    |    |    \--- io.micrometer:micrometer-core:1.1.1
|    |    |         +--- org.latencyutils:LatencyUtils:2.0.3
Run Code Online (Sandbox Code Playgroud)

这似乎发生在Spring Boot 2.0.6以及2.1.1上.

典型的测试可能如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@ActiveProfiles(profiles = {"test"})
public class MyTest {
[...]
Run Code Online (Sandbox Code Playgroud)

我的执行器配置如下所示:

management.endpoints.enabled-by-default=false
management.endpoint.prometheus.enabled=true
management.endpoints.web.base-path=/
management.endpoints.web.exposure.include=prometheus
management.endpoints.web.path-mapping.prometheus=prometheus
spring.metrics.prometheus.enabled=true
Run Code Online (Sandbox Code Playgroud)

请参见附件截图

在此输入图像描述

Eri*_*vic 12

来自Pivotal的Snicoll通过建议它可能与Spring启动测试框架中的上下文缓存相关联来帮助我使用GitHub.

如果您有大量使用spring集成的测试和一些有用的上下文配置(您只显示了一个类),那么每个配置将创建一个上下文,我可以看到线程数增加了那个场景.

然后他向我指出了相关文件,其中说明:

您可以通过设置名为spring.test.context.cache.maxSize的JVM系统属性,从命令行或构建脚本配置最大大小.或者,您可以使用SpringProperties API以编程方式设置相同的属性.

org.springframework.core.SpringProperties指出:

Reads a {@code spring.properties} file from the root of the Spring library classpath
Run Code Online (Sandbox Code Playgroud)

这让我们有两种设置方式maxSize.

选项1.配置gradle测试任务

将属性添加到gradle test任务,该任务将GradleWorkerMainbuild.gradle以下位置配置:

test {
    jvmArgs "-Dspring.test.context.cache.maxSize=1"
}
Run Code Online (Sandbox Code Playgroud)

如果您有许多子项目,则可能需要使用此选项.

有关将设置应用于所有子项目的方法,请参阅下面的奖励.

选项2.将spring.properties添加到测试资源

您可以编写设置my-service/src/test/resources/spring.properties,如下所示:

spring.test.context.cache.maxSize=1
Run Code Online (Sandbox Code Playgroud)

结论

现在我的测试运行得很好,内存消耗更少,线程更少.

奖金

这也解决了Gradle 5+的问题,默认情况下工作组最大堆数为512MB(而不是系统RAM的25%) - 子项目测试套件不再吹走所有可用的RAM,如果我这样做会导致工作人员进入OOM不要在项目test配置中添加具有更大堆的自定义jvmargs java.我现在可以在gradle worker中以"vanilla"堆大小运行.

如果确实想调整Gradle测试可用的RAM,请在root中执行以下操作build.gradle:

allprojects { project ->
    project.plugins.withId('java') {
        test {
            maxHeapSize = "1536M"
            // If you don't want to use spring.properties (or add other JVM args)
            jvmArgs "-Dspring.test.context.cache.maxSize=1"
        }
    }
    project.plugins.withId('java-library') {
        test {
            maxHeapSize = "1536M"
            // If you don't want to use spring.properties (or add other JVM args)
            jvmArgs "-Dspring.test.context.cache.maxSize=1"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)