如何解决用于构建 spring-boot 应用程序的 Paketo buildpack 的内存问题?

edb*_*ras 14 amazon-web-services amazon-elastic-beanstalk spring-boot-maven-plugin paketo

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

我正在使用总 RAM 为 1G 的 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>
Run Code Online (Sandbox Code Playgroud)

部署期间 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

Dan*_*usa 11

好的,这就是这告诉我们的:

根据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/meminfo来检查系统的最大可用内存。MemAvailable
  3. 如果一切都失败了,最终会以 1G 回退告终。

如果它确实无法按照上述方式工作,请打开一个错误并提供尽可能多的详细信息。


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

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

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

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

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