【问题标题】:How to solve Memory issues with Paketo buildpack used to build a spring-boot app?如何解决用于构建 spring-boot 应用程序的 Paketo buildpack 的内存问题?
【发布时间】:2021-08-08 03:32:07
【问题描述】:

我正在使用部署到 AWS BeanStalk 的 spring-boot-maven-plugin 构建 Docker 映像。我通过2.4.3 spring boot starter依赖使用插件) 但是,当容器启动时,我收到以下错误。 我对 buildpack 的东西有点陌生,但试图通过使用网站上描述的 Buildpack env 变量来解决它。但它对下面错误日志中显示的值绝对没有影响。 我找到了这个github issue,但不确定它是否相关以及如何使用它。

我正在使用具有 1G 总 RAM 的 AWS Micro 实例,它执行滚动更新,因此在启动新映像时,另一个也在运行,直到新映像启动成功,所以启动容器可以也只有 300MB 可用,但是,在正常运行期间它有更多可用空间。

为什么我需要这个内存计算?我不能禁用它吗?当我构建 app.jar 的 Docker 映像并将其部署到 aws beanstalk 时,它在没有任何内存设置的情况下运行良好:

码头工人建造。 --build-arg JAR_FILE=./target/app.jar -t $APPLICATION_NAME

但我很想通过 spring-boot-maven 插件使用镜像构建。 请教一下如何解决这个问题?

        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <image>
                    <name>${image.name}</name>
                    <env>
                        <tag>${project.version}</tag>
                        <!--BPE_APPEND_JAVA_TOOL_OPTIONS>-XX:MaxDirectMemorySize=1M</BPE_APPEND_JAVA_TOOL_OPTIONS-->
                        <BPE_JAVA_TOOL_OPTIONS>-Xms1024m -Xmx3048m</BPE_JAVA_TOOL_OPTIONS>
                    </env>
                </image>
            </configuration>
        </plugin>

部署期间的 AWS Beanstalk 错误:

Tue May 18 2021 18:07:14 GMT+0000 (UTC)   INFO   Successfully built aws_beanstalk/staging-app
Tue May 18 2021 18:07:22 GMT+0000 (UTC)   ERROR   Docker container quit unexpectedly after launch: 0M, -Xss1M * 250 threads
[31;1mERROR: [0mfailed to launch: exec.d: failed to execute exec.d file at path '/layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/memory-calculator': exit status 1. Check snapshot logs for details.
Tue May 18 2021 18:07:24 GMT+0000 (UTC)   ERROR   [Instance: i-0dc33dcb517e89ef9] Command failed on instance. Return code: 1 Output: (TRUNCATED)...pectedly after launch: 0M, -Xss1M * 250 threads
[31;1mERROR: [0mfailed to launch: exec.d: failed to execute exec.d file at path '/layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/memory-calculator': exit status 1. Check snapshot logs for details. 
Hook /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh failed. For more detail, check /var/log/eb-activity.log using console or EB CLI.
Tue May 18 2021 18:07:24 GMT+0000 (UTC)   INFO   Command execution completed on all instances. Summary: [Successful: 0, Failed: 1].
Tue May 18 2021 18:07:24 GMT+0000 (UTC)   ERROR   Unsuccessful command execution on instance id(s) 'i-0dc33dcb517e89ef9'. Aborting the operation.
Tue May 18 2021 18:07:24 GMT+0000 (UTC)   ERROR   Failed to deploy application.
Tue May 18 2021 18:07:24 GMT+0000 (UTC)   ERROR   During an aborted deployment, some instances may have deployed the new application version. To ensure all instances are running the same version, re-deploy the appropriate application version.
##[error]Error: Error deploy application version to Elastic Beanstalk

在 AWS Beanstalk 中下载的 Docker 错误日志:

Docker container quit unexpectedly on Tue May 18 18:07:21 UTC 2021:
Setting Active Processor Count to 1
Calculating JVM memory based on 274300K available memory
unable to calculate memory configuration
fixed memory regions require 662096K which is greater than 274300K available for allocation: -XX:MaxDirectMemorySize=10M, -XX:MaxMetaspaceSize=150096K, -XX:ReservedCodeCacheSize=240M, -Xss1M * 250 threads
[31;1mERROR: [0mfailed to launch: exec.d: failed to execute exec.d file at path '/layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/memory-calculator': exit status 1

【问题讨论】:

    标签: amazon-web-services amazon-elastic-beanstalk spring-boot-maven-plugin paketo


    【解决方案1】:

    好的,这就是它告诉我们的内容:

    根据 274300K 可用内存计算 JVM 内存

    内存计算器检测到容器中的最大可用内存量为 274300KB,或大约 274M。

    固定内存区域需要 662096K,大于 274300K 可用于分配:-XX:MaxDirectMemorySize=10M, -XX:MaxMetaspaceSize=150096K, -XX:ReservedCodeCacheSize=240M, -Xss1M * 250 个线程

    此消息表示内存计算器在其当前配置中至少需要 662096KB 或 662M。

    它也分解了它为什么需要/想要那么多:

    • 10M 用于直接内存
    • 150096K 用于元空间
    • 240M 用于保留代码缓存
    • 250M 用于线程(特别是线程堆栈)

    这还不包括需要更多的堆(你似乎需要至少 1G 的堆)。

    这留下了两种可能性:

    1. 容器的配置不够大。你需要给它更多的内存。
    2. 内存计算器未正确检测内存限制。

    如果您怀疑 #2,请查看以下内容。内存计算器通过按顺序查看这些位置来选择它的最大内存限制(即上例中的 274M)。

    1. 通过查看容器内的/sys/fs/cgroup/memory/memory.limit_in_bytes 检查配置的容器内存限制。
    2. 再次从容器内部查看/proc/meminfoMemAvailable 指标,检查系统的最大可用内存。
    3. 如果所有其他方法都失败了,它将以 1G 回退结束。

    如果确实无法按上述方式工作,请please open a bug 并提供尽可能多的详细信息。


    或者,您可以调整内存计算器。您可以指示它为特定区域分配更少的内存,从而将所需的总内存减少到小于最大可用内存。

    您可以通过在 JAVA_TOOL_OPTIONS 环境变量中设置 JVM 内存标志来做到这一点(您有 BPE_JAVA_TOOL_OPTIONS 这是不正确的)。见https://paketo.io/docs/buildpacks/language-family-buildpacks/java/#runtime-jvm-configuration

    例如,如果您想覆盖堆大小,则将 -Xmx 中的 -Xmx 设置为自定义值。内存计算器将查看您设置的内容并相应地调整剩余的内存设置。尽可能多地覆盖。

    要使内存大小适合 274M 的内存,您必须做得非常小。像-Xss256K -XX:ReservedCodeCacheSize=64M -XX:MaxMetaspaceSize=64 -Xmx64M 这样的东西。我没有进行测试以确认,但这显示了您需要做什么的想法。减少内存设置,使总和都符合容器的最大内存限制。

    这也没有考虑您的应用程序是否真的能够在如此小的限制内运行。如果你太小,你可能会在某些时候看到 OutOfMemoryErrors 或 StackOverflowErrors,你的应用程序将会崩溃。您还可以通过过多减少代码缓存大小来对性能产生负面影响,因为这是 JIT 存储字节码的地方,它已针对本机代码进行了优化。如果堆的大小不合适,您甚至可能会导致 GC 问题,或者由于过多的 GC 而导致性能下降。简而言之,如果您要这样做,请务必小心。

    【讨论】:

    • 我正在使用总内存为 1G 的 AWS Micro 实例,它执行滚动更新,所以在启动新镜像时,另一个也在运行,直到新镜像启动成功,所以启动包含也可能只有 300MB 可用,但是,在正常运行期间它有更多可用空间。如何完全禁用内存计算?为什么需要它?当我构建 app.jar 的 Docker 映像并将其部署到 aws beanstalk 时,它运行良好,但它不像 paketo 那样分层和优化。 (我还在上面的问题中添加了这段文字)
    • 没有禁用内存计算器的选项。内存计算器的功能是确保您的应用程序不超过容器的内存限制。我不知道 AWS 在这方面的情况如何,但是大多数系统会在您超出定义的内存限制时终止您的应用程序,因此内存计算器有效地确保您的应用程序不会不必要地崩溃。跨度>
    • to start the contains could as well be that only 300MB is available -> 这似乎不太可能。内存计算器正在查看/proc 文件系统(即内核)指示的可用内存量。这基本上是系统中可用的物理内存。如果在内核启动后这种情况发生了变化,那将是非常奇怪的。如果您编写一个简单的测试应用程序并让它打印我上面列出的文件的值,您可以确认。
    • 嗯,很有趣,感谢您的清晰解释,但是如果我如上所述直接创建自己的 Docker 映像(没有多层)并在没有任何内存设置的情况下部署它,为什么映像运行良好AWS beanstalk(这是我们仍在做和工作的)。我理解正确,这会导致内存问题,但应用程序运行得很好(在最大 1GB Ram 的微型容器上已经运行了 2 年)......我很困惑......
    • 很难说,因为我不知道你是如何运行非 buildpack 生成的镜像的。 buildpack 生成的映像旨在在具有硬限制的系统中运行,因此它会尽其所能确保您的应用程序不会超出这些限制。如果您在没有硬限制的地方运行 Dockerfile 生成的映像,那么如何配置 JVM 并不重要。你可以告诉它你想要 5 倍的可用内存。在JVM尝试实际使用它之前它可能不会失败,即使那样它也可能只是交换。这取决于很多因素。
    猜你喜欢
    • 2022-10-19
    • 2019-06-06
    • 2021-09-15
    • 1970-01-01
    • 2019-07-04
    • 2021-09-26
    • 2017-08-09
    • 2019-07-24
    • 1970-01-01
    相关资源
    最近更新 更多