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

标签 java spring spring-boot

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

在运行测试时,它似乎积累了很多线程,其中一个线程有多个实例并且被称为SimplePauseDetectorThread_0,我追溯到这个依赖

|    |    |    \--- io.micrometer:micrometer-core:1.1.1
|    |    |         +--- org.latencyutils:LatencyUtils:2.0.3

这似乎发生在 Spring Boot 2.0.6 和 2.1.1 上。

一个典型的测试可能是这样的:

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

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

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

见附件截图

enter image description here

最佳答案

Snicoll from Pivotal helped me on GitHub ,通过暗示它可能连接到 spring boot 测试框架中的上下文缓存。

If you have a large number of tests that are using the spring integration and a somewhat important number of context configurations (you've only shown one class), then one context per configuration will be created and I can see the number of threads increasing in that scenario.

然后他将我指向了 relevant documentation ,其中指出:

You can configure the maximum size from the command line or a build script by setting a JVM system property named spring.test.context.cache.maxSize. As an alternative, you can set the same property programmatically by using the SpringProperties API.

org.springframework.core.SpringProperties 声明:

Reads a {@code spring.properties} file from the root of the Spring library classpath

这给我们留下了两种设置 maxSize 的方法。

方案一.配置gradle测试任务

build.gradle 中向 gradle test 任务添加一个属性,它将配置 GradleWorkerMain:

test {
    jvmArgs "-Dspring.test.context.cache.maxSize=1"
}

如果您有很多子项目,您可能希望使用此选项。

请参阅下面的Bonus,了解将设置应用于所有子项目的方法。

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

你可以把设置写在my-service/src/test/resources/spring.properties中,像这样:

spring.test.context.cache.maxSize=1

结论

现在我的测试运行良好,内存消耗更少,线程更少。

奖金

这也解决了 Gradle 5+ 默认情况下拥有 512MB 最大堆(而不是系统 RAM 的 25%)的 worker 的问题 - 子项目测试套件不再耗尽所有可用 RAM,这会导致 worker OOM如果我没有在 java 项目的 test 配置中添加具有更大堆的自定义 jvmargs。我现在可以在 gradle worker 中以“vanilla”堆大小运行。

如果确实想调整可用于 Gradle 测试的 RAM,请在根 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"
        }
    }
}

关于java - Spring 集成测试消耗大量内存,在 GradleWorkerMain 中使用大量重复线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54117965/

相关文章:

java - 选择组合框中的项目时执行操作

java - GWT 滚动条未出现

java - 不带修剪的自由标记列表

java - 无法使用 Spring Boot 提供静态资源

java - 映射嵌套 beans 列表 : "org.mapstruct.Mapping"

java - 使用 Junit5 在 Spring Boot 应用程序中测试服务层时如何避免数据库连接

java - 这是允许通配符搜索用户的正确方法吗?

spring - JBoss 5.1 : Entity classes not found (vfszip)

使用 Spring Boot 的 Spring Data Rest 和 spring-data-rest-hal-browser 集成

java - 在 JComboBox 中使用向上/向下箭头滚动时,它不应该更新显示所选项目的顶部图 block