代码之家  ›  专栏  ›  技术社区  ›  surfspider

swisscom cloudfoundry springboot应用程序内存不足

  •  6
  • surfspider  · 技术社区  · 7 年前

    我有一个SpringBoot应用程序,它最多只需要284 MB内存。但我只能启动最大内存为768 MB的应用程序。即使以后减少内存,我也总是会遇到以下错误:

    [APP/PROC/WEB/0] ERR Cannot calculate JVM memory configuration: There is insufficient memory remaining for heap. Memory limit 384M is
    less than allocated memory 672509K (-XX:ReservedCodeCacheSize=240M, -XX:MaxDirectMemorySize=10M, -XX:MaxMetaspaceSize=109309K, -Xss1M * 300 threads)
    

    我已经在cf中使用了相同的应用程序,没有这个问题。cf中发生了什么变化?在2到3周之前,它仍然有效。

    提前感谢您的快速回答!

    2 回复  |  直到 7 年前
        1
  •  6
  •   Daniel Mikusa    7 年前

    我已经在cf中使用了相同的应用程序,没有这个问题。cf中发生了什么变化?在2到3周之前,它仍然有效。

    您必须已升级到Java Build Pack v4。使用JBP v3,您可以推送内存量较小的应用程序,但使用该版本的buildpack和较小内存限制推送的应用程序也很容易崩溃。这是因为JBP v3在进行计算时没有考虑JVM使用的所有内存区域,所以虽然它可以让你的应用程序启动,但以后应用程序仍然可以超过它的内存限制。JBP v4计算内存的方式现在更加精确,并且考虑了JVM的所有内存区域。

    最终的结果是,对于运行RAM小于1G的JBP v4应用程序,可以在登台时看到以下错误,而运行RAM小于等于512M的应用程序几乎肯定会在登台时看到此错误:

    ERR Cannot calculate JVM memory configuration: There is insufficient memory remaining for XXXX
    

    然而,要成功完成stage的Java应用程序有 明显地 不太可能崩溃。

    https://discuss.pivotal.io/hc/en-us/articles/115011717548-Insufficient-memory-when-using-Java-Buildpack-4-0-

    那么,这是否意味着您不能用少于1G的RAM运行Java应用程序?不,可以,但需要一些调整。这里列出了一些可以优化以节省内存的内容。

    • 线程计数。JBP假设您的应用程序将运行250个线程。这对于Web应用程序来说非常常见,其中大约有50个用于Tomcat的内部内容,200个用于请求处理。你可以降低这个值,但你需要确保你的应用程序不超过你设置的线程数,否则你的应用程序会崩溃。对于您来说,这将通过Spring Boot调整Tomcat的配置。

      JBP的较低线程数示例:

      cf set-env my-application JBP_CONFIG_OPEN_JDK_JRE '{ memory_calculator: { stack_threads: 50 } }'

      Spring Boot应用程序中的较低线程数示例。属性:

      server.tomcat.max-threads=25

      注意:这只是请求处理线程。Tomcat本身有线程,您的应用程序也可以创建线程。你真的应该查看线程转储或JVisualVM,看看你的应用程序需要多少线程(即测量,不要猜测)

    • 线程堆栈大小(-Xss)。这是一个传递给JVM的值,JVM控制每个线程需要多少内存。默认值为1M,非常高。在大多数情况下,您可以安全地将其降低到160K,这是Java 8允许的最小值。如果您有250个线程并进行此更改,则将节省(1M*250)-(160K-250)=211M的RAM。

      注意:如果线程堆栈大小降低太多,则会在应用程序中看到StackOverflow异常。如果发生这种情况,保持冷静,提高价值,直到他们离开。

    • 降低保留代码缓存。这是JVM缓存JIT代码的地方。默认为240M。您可以降低此值,但要小心,因为这绝对会影响性能。您还可以看到 errors at runtime if this value is not high enough .

      同样,最好是衡量你的应用程序需要什么,而不是猜测。您应该能够使用 JVM's NMT .

    • 您可以手动调整JVM使用的其他内存区域,如Heap&元空间。使用JBP v4,只需使用 cf set-env 或者在你的 manifest.yml 文件显然,如果你降低这些值,你需要小心不要太低,在这种情况下,你最终会出现OutOfMemoryErrors。

      注意:如果您未设置一个区域,如堆或元空间,JBP将使用手动自定义后剩余的任何内容智能地计算它。

    希望有帮助!

        2
  •  2
  •   fischermatte    7 年前

    我不是cloud foundry中java应用程序内存处理方面的专家,但据我所知,人们需要了解以下几点:

    • Java应用程序通常通过 Java Buildpack . 如果你 不要在清单中定义版本。yml需要主人 树枝由于主分支一直在变化,我假设 部署参数也可能会更改。
    • Java构建包使用 Java Buildpack Memory Calculator 评估JVM内存参数,如 -Xmx . 您可以在清单中自己配置这些参数。yml,但如果要使用cloud foundry的缩放功能,则不建议使用。
    • 因此,当您定义允许您的cloud foundry应用程序使用500MB内存,并且构建包计算器的计算结果更高时,它可能无法工作,并导致一些错误。

    在清单中可以做的是处理内存计算器文档中提到的所有这些参数。例如,您可以给计算器一个提示,即您需要更少的线程(例如。 memory_calculator: { stack_threads: 100} )

    当您可以“硬编码”一些内存参数时:这里是一个示例清单。我使用的Spring Boot 2/Java 9应用程序的yml限制为400 MB。它对我很有用,但可能不是什么可以马上复制的东西。这取决于你的应用程序。

    applications:
    - name: demo-app
      path: target/demo-app-1.0.0.jar
      instances: 1
      buildpack: https://github.com/cloudfoundry/java-buildpack.git
      memory: 400m
      env:
        JAVA_OPTS: '-XX:MaxMetaspaceSize=80780K -Xss512k -Xmx200M -XX:ReservedCodeCacheSize=16M -XX:MaxDirectMemorySize=16M'
        JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 9.+ } }'
    
    推荐文章