Java-buildpack: 无法使用默认配置和 <512M 运行 Spring Boot 应用程序

创建于 2018-12-31  ·  8评论  ·  资料来源: cloudfoundry/java-buildpack

无法运行小于 512M 的 Spring Boot hello world(MVC 或 WebFlux)以及大多数非平凡应用程序在 Cloud Foundry 上至少需要 1G 的事实对用户来说非常令人沮丧,并给人一种错误的印象,即 Spring少于 1G 的内存无法启动。

我们正在与@dsyer 、Boot 团队和其他人一起做一些工作来优化 Spring Framework 和 Spring Boot,以减少 GC 压力并降低内存消耗,但我倾向于认为我们还可以改进 Cloud Foundry 以更好的方式处理这个问题。

我已经提出了关于内存计算规则的https://github.com/cloudfoundry/java-buildpack-memory-calculator/issues/24

另一点:如果通过计算应用程序中的所有.class文件(包括其依赖项)来计算类的数量,那么对于没有非常细粒度的 JAR 粒度的 Spring 应用程序来说,它不是可靠的信息来源,并且会仅有效加载 Spring JAR 上可用类的一小部分。

这个问题在我们在 Spring Boot 2.1 中提供的优化以及我们目前正在为 Spring Boot 2.2 进行的优化中更加明显。

我的直觉是,典型用户知道他们的应用程序在本地需要多少Xmx内存,我们也许应该默认使用该信息。

question

最有用的评论

通过配置内存计算器,可以在512M以下运行。
以下清单对我有用(spring boot + webflux)。

applications:
- name: myapp
  path: target/myapp-0.0.1-SNAPSHOT.jar
  memory: 256m
  env:
    JAVA_OPTS: '-XX:ReservedCodeCacheSize=32M -XX:MaxDirectMemorySize=32M'
    JBP_CONFIG_OPEN_JDK_JRE: '[memory_calculator: {stack_threads: 30}, jre: {version: 11.+}]'

一个普通的 webflux 应用程序实际上只运行 60MB 内存。

我是内存计算器的忠实粉丝,因为大多数开发人员往往只关心堆大小并获得意外的 OOME(例如 Metaspace),但我同意我们可以改进它。
计算器中的默认线程大小(300?)至少对于 webflux 来说太大了。

对于初学者来说,很难找到自定义内存大小的方法。
README 中用例的配置示例将非常有帮助。

所有8条评论

通过配置内存计算器,可以在512M以下运行。
以下清单对我有用(spring boot + webflux)。

applications:
- name: myapp
  path: target/myapp-0.0.1-SNAPSHOT.jar
  memory: 256m
  env:
    JAVA_OPTS: '-XX:ReservedCodeCacheSize=32M -XX:MaxDirectMemorySize=32M'
    JBP_CONFIG_OPEN_JDK_JRE: '[memory_calculator: {stack_threads: 30}, jre: {version: 11.+}]'

一个普通的 webflux 应用程序实际上只运行 60MB 内存。

我是内存计算器的忠实粉丝,因为大多数开发人员往往只关心堆大小并获得意外的 OOME(例如 Metaspace),但我同意我们可以改进它。
计算器中的默认线程大小(300?)至少对于 webflux 来说太大了。

对于初学者来说,很难找到自定义内存大小的方法。
README 中用例的配置示例将非常有帮助。

@making我已经更新了这个问题的标题,以更清楚地说明它是关于(至少)引导应用程序的默认配置是次优的。 当然,使用 256M 和自定义配置运行引导应用程序是完全可能的,但在我看来,默认内存配置离准确很远,我希望我们在这方面取得一些进展,因为它影响了很多用户。

您提到的 WebFlux 应用程序的线程数确实是一个非常有趣的点,构建包可以通过检测它是哪种应用程序来提供额外的附加值。 这可能很棘手,因为某些 MVC 应用程序可以使用 Reactive WebClient ,但我相信我们可以做一些更聪明和准确的事情。

您的自定义内存配置突出了 IMO 自动配置机制中的问题。 如https://github.com/cloudfoundry/java-buildpack-memory-calculator/issues/24 中所述,如果我明确指定 Boot 应用程序有效使用的类数(8000 到 10000 之间),则生成的参数为-XX:ReservedCodeCacheSize=240M ,您在其中指定-XX:ReservedCodeCacheSize=32M 。 这种差异真的很大,我们可以做出更有根据的猜测吗?

此外,8000 或 10000 是引导应用程序有效使用的分类数。 如果构建包是根据应用程序中的类数+依赖项计算的,我倾向于认为指定给内存计算器的类数会人为地高(我仍然需要检查当前猜测的值,但构建包)由于 Spring Framework JAR 的性质。

我还想知道我们是否利用最新的 Java 8 和 Java 11 中提供的新容器内存选项。它们是为 Docker 设计的,但我想我们也可以在 Cloud Foundry 中受益。 尽管 CF 没有使用 Docker,Java 运行时是否知道我们正在容器中运行? 我们是否利用-XX:InitialRAMPercentage-XX:MaxRAMPercentage-XX:MinRAMPercentage

这是一个棘手的问题@sdeleuze。 java-buildpack 是否使用 java 默认值,我们假设一些想法进入了 java 设置,默认情况下允许应用程序运行,更像是它们不在 CF 中运行时所做的那样? 或者 java-buildpack 是否更改了默认设置以改善初始体验,但是当应用程序没有按预期运行而不是在 CF 中时让用户搜索答案?

今天,java-buildpack 选择使用 java 和 tomcat 默认值作为今天的典型应用程序信任这些值。 我个人更喜欢这种方法,而不是更改可能以对用户不太明显/不明确的方式影响应用程序的 Java 默认值。

就新属性而言,我对RAMPercentage属性的理解是,它们只是根据可用内存的百分比自动设置堆值。 没有考虑非堆内存要求,如代码缓存大小、线程堆栈大小、元空间、GC 内存开销等。这项工作仍然留给用户练习,以猜测他们的应用程序需要多少非堆内存。 我期待有一天 java 可以简单地正确管理所有内存池,以将应用程序保持在容器的内存限制内。 但我怀疑我们离这一点还有很长的路要走。

作为旁注,这是我为我的应用程序设置的 JAVA_OPTS 和 jre 配置,我需要在低内存和速度的情况下保持稳定。

  • 我将 MaxMetaSize 设置为通过分析发现的。
    JAVA_OPTS
-Xss256K -Xms1M -XX:+UseSerialGC -Djava.compiler=none -XX:ReservedCodeCacheSize=2496k -XX:MaxDirectMemorySize=1M

配置文件

  stack_threads: 20
此页面是否有帮助?
0 / 5 - 0 等级

相关问题

metacubed picture metacubed  ·  6评论

ipsi picture ipsi  ·  12评论

aknobloch picture aknobloch  ·  8评论

ajay-dbs picture ajay-dbs  ·  21评论

kmacpher67 picture kmacpher67  ·  28评论