Java-buildpack: Imposible ejecutar aplicaciones Spring Boot con configuración predeterminada y <512M

Creado en 31 dic. 2018  ·  8Comentarios  ·  Fuente: cloudfoundry/java-buildpack

El hecho de que no sea posible ejecutar un Spring Boot hello world (MVC o WebFlux) con menos de 512M y que la mayoría de las aplicaciones no triviales requieran al menos 1G en Cloud Foundry es bastante frustrante para los usuarios y da la falsa impresión de que Spring El arranque no se puede ejecutar con menos de 1G de memoria.

Estamos trabajando con @dsyer , el equipo de arranque y otros para optimizar Spring Framework y Spring Boot para generar menos presión de GC y tener un menor consumo de memoria, pero tiendo a pensar que también podríamos mejorar Cloud Foundry para manejar eso de una mejor manera.

He planteado https://github.com/cloudfoundry/java-buildpack-memory-calculator/issues/24 sobre la regla de cálculo de memoria.

Otro punto: si el número de clases se calcula contando todos los archivos .class en la aplicación, incluidas sus dependencias, no es una fuente confiable de información para las aplicaciones Spring que no tiene una granularidad JAR muy fina y cargue de manera efectiva solo una pequeña proporción de las clases disponibles en Spring JAR.

El problema es aún más visible con las optimizaciones que enviamos en Spring Boot 2.1 y la optimización en la que estamos trabajando actualmente para Spring Boot 2.2.

Mi intuición es que los usuarios típicos saben cuánta Xmx memoria necesita localmente su aplicación, y tal vez deberíamos usar esa información de forma predeterminada.

question

Comentario más útil

Es posible ejecutar con menos de 512M configurando la calculadora de memoria.
El siguiente manifiesto funciona para mí (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.+}]'

Una aplicación vanilla webflux en realidad se ejecuta con solo

Soy un gran fanático de la calculadora de memoria ya que la mayoría de los desarrolladores tienden a preocuparse solo por el tamaño del montón y obtienen un OOME inesperado (por ejemplo, Metaspace), pero estoy de acuerdo en que podríamos mejorarlo.
El tamaño de hilo predeterminado (300?) En la calculadora sería demasiado grande para al menos webflux.

Para los principiantes, es bastante difícil encontrar la manera de personalizar el tamaño de la memoria.
Los ejemplos de configuración por caso de uso en README serían muy útiles.

Todos 8 comentarios

Es posible ejecutar con menos de 512M configurando la calculadora de memoria.
El siguiente manifiesto funciona para mí (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.+}]'

Una aplicación vanilla webflux en realidad se ejecuta con solo

Soy un gran fanático de la calculadora de memoria ya que la mayoría de los desarrolladores tienden a preocuparse solo por el tamaño del montón y obtienen un OOME inesperado (por ejemplo, Metaspace), pero estoy de acuerdo en que podríamos mejorarlo.
El tamaño de hilo predeterminado (300?) En la calculadora sería demasiado grande para al menos webflux.

Para los principiantes, es bastante difícil encontrar la manera de personalizar el tamaño de la memoria.
Los ejemplos de configuración por caso de uso en README serían muy útiles.

@making He actualizado el título de este número para dejar más claro que se trata de que la configuración predeterminada es subóptima para (al menos) aplicaciones de arranque. Por supuesto, es totalmente posible ejecutar aplicaciones de arranque con 256M y configuración personalizada, pero la configuración de memoria predeterminada me parece muy, muy lejos de ser precisa y ahí es donde me gustaría que progresáramos, porque impacta a muchos usuarios.

La cantidad de subprocesos que menciona para la aplicación WebFlux es de hecho un punto muy interesante, el paquete de compilación podría proporcionar un valor agregado adicional al detectar qué tipo de aplicación es. Puede ser complicado ya que algunas aplicaciones MVC pueden usar Reactive WebClient , pero estoy seguro de que podemos hacer algo más inteligente y preciso.

Su configuración de memoria personalizada resalta IMO que algo anda mal en el mecanismo de configuración automática. Como se explica en https://github.com/cloudfoundry/java-buildpack-memory-calculator/issues/24 , si especifico explícitamente el número de clases (entre 8000 y 10000) utilizadas efectivamente por las aplicaciones de arranque, el parámetro generado es -XX:ReservedCodeCacheSize=240M , donde especifica -XX:ReservedCodeCacheSize=32M . Esta diferencia es realmente enorme, ¿podríamos hacer una suposición más fundamentada?

Además, 8000 o 10000 son algunas de las aplicaciones de arranque clasificadas que se utilizan de forma eficaz. Si el paquete de compilación calcula eso a partir del número de clases en la aplicación + dependencias, tiendo a pensar que el número de clases especificadas en la calculadora de memoria será artificialmente alto (todavía necesito verificar el valor que se adivina actualmente, pero el paquete de compilación) debido a la naturaleza de los JAR de Spring Framework.

También me pregunto si aprovechamos las nuevas opciones de memoria de contenedor que están disponibles en la última versión de Java 8 y en Java 11. Están diseñadas para Docker, pero supongo que también podríamos beneficiarnos de esto en Cloud Foundry. ¿El tiempo de ejecución de Java es consciente de que estamos ejecutando en contenedores a pesar de que CF no usa Docker? ¿Aprovechamos opciones como -XX:InitialRAMPercentage , -XX:MaxRAMPercentage o -XX:MinRAMPercentage ?

Es un problema complicado @sdeleuze. ¿Java-buildpack usa valores predeterminados de Java, que asumimos que se pensó en la configuración de Java, lo que permite que las aplicaciones funcionen, de forma predeterminada, más como lo hacen cuando no se ejecutan en CF? ¿O el paquete de compilación de java cambia los valores predeterminados para mejorar la experiencia inicial, pero luego deja a los usuarios buscando respuestas cuando la aplicación no se ejecuta como se esperaba, no en CF?

Hoy, java-buildpack ha optado por utilizar los valores predeterminados de java y tomcat confiando en esos valores como una aplicación típica en la actualidad. Personalmente, me gusta más ese enfoque que cambiar los valores predeterminados de Java que pueden afectar la aplicación de maneras no muy visibles / explícitas para el usuario.

En lo que respecta a las nuevas propiedades, mi comprensión de las propiedades RAMPercentage es que simplemente establecen valores de montón automáticamente en función de un porcentaje de RAM disponible. No hay que pensar en los requisitos de memoria no dinámica como el tamaño de la memoria caché del código, el tamaño de la pila de subprocesos, el metaespacio, la sobrecarga de la memoria GC, etc. Ese trabajo todavía se deja como un ejercicio para que el usuario adivine cuánta memoria no dinámica necesita su aplicación. Espero con ansias el día en que Java pueda simplemente administrar todos los grupos de memoria correctamente para mantener una aplicación dentro de las limitaciones de memoria de un contenedor. Pero sospecho que todavía estamos muy lejos de eso.

Como nota al margen, esta es la configuración de JAVA_OPTS y jre que configuré para mis aplicaciones que necesito para ser estable con poca memoria y la velocidad no es un factor.

  • Configuré MaxMetaSize en un descubierto a través de la creación de perfiles.
    JAVA_OPTS
-Xss256K -Xms1M -XX:+UseSerialGC -Djava.compiler=none -XX:ReservedCodeCacheSize=2496k -XX:MaxDirectMemorySize=1M

jre config

  stack_threads: 20
¿Fue útil esta página
0 / 5 - 0 calificaciones