首页 > 解决方案 > 如何在 docker 环境中解决 gradle 被破坏的问题?

问题描述

Gradle 在 docker 环境下无法正常工作,它注定会使用过多的内存并因使用过多的内存而被杀死。

内存管理器使用以下类获取其快照

https://github.com/gradle/gradle/blob/master/subprojects/process-services/src/main/java/org/gradle/process/internal/health/memory/MemInfoOsMemoryInfo.java

特别是 Gradle 通过读取 /proc/meminfo 来确定剩余多少可用内存,这会在容器中提供不准确的读取。

Gradle 仅在收到请求以创建具有更大最小堆大小的新 Worker Daemon 时才会杀死 Worker Daemons,然后根据此读数可用。

因此,Gradle 将继续制造工人,直到它用完容器的分配数量并被杀死。

有没有人有解决方法?真的不明白这对更多人来说如何不是问题。我想只有当你的工作守护进程不能被重用并且创建新的守护进程时才会真正成为一个问题,这对我来说就是这种情况,因为我有大量的模块。

我有一个临时的解决方法,我给每个 jvm 生成一个巨大的 -Xms ,所以它总是触发最小堆大小>可用,所以总是删除以前的工作守护进程,但这并不令人满意。

- 编辑

为了抢占某些东西,--max-workers 不会影响允许存在的 Worker 守护进程的数量,它只会影响允许处于活动状态的数量。即使使用 --max-workers = 1,也允许任意多个空闲的 Worker 守护进程。

标签: dockerjenkinsgradle

解决方案


编辑 - 忽略下面,它有点工作,但我已经通过覆盖 MemInfoOsMemoryInfo 类修补了 Gradle,它工作得更好。将很快提供到 MR 到 Gradle 的链接。

找到了一个合理的解决方法,我们监听操作系统内存更新,每次任务完成时,我们请求的内存比确定的可用内存多,确保守护进程停止。

import org.gradle.process.internal.health.memory.OsMemoryStatus
import org.gradle.process.internal.health.memory.OsMemoryStatusListener
import org.gradle.process.internal.health.memory.MemoryManagertask 

task expireWorkers {
    doFirst {
        long freeMemory = 0

        def memoryManager = services.get(MemoryManager.class)
        gradle.addListener(new TaskExecutionListener() {
            void beforeExecute(Task task) {
            }
            void afterExecute(Task task, TaskState state) {
                println "Freeing up memory"
                memoryManager.requestFreeMemory(freeMemory * 2)
            }
        })
        memoryManager.addListener(new OsMemoryStatusListener() {
            void onOsMemoryStatus(OsMemoryStatus osMemoryStatus) {
                freeMemory = osMemoryStatus.freePhysicalMemory
            }
        })
    }
}

推荐阅读