Java-buildpack: Es ist nicht möglich, Spring Boot-Anwendungen mit Standardkonfiguration und <512M . auszuführen

Erstellt am 31. Dez. 2018  ·  8Kommentare  ·  Quelle: cloudfoundry/java-buildpack

Die Tatsache, dass es nicht möglich ist, eine Spring Boot-Hello-Welt (MVC oder WebFlux) mit weniger als 512 MB zu betreiben und dass die meisten nicht trivialen Anwendungen mindestens 1 GB auf Cloud Foundry benötigen, ist für Benutzer ziemlich frustrierend und erweckt den falschen Eindruck, dass Spring Boot kann nicht mit weniger als 1 GB Arbeitsspeicher ausgeführt werden.

Wir arbeiten mit @dsyer , dem Boot-Team und anderen zusammen, um Spring Framework und Spring Boot zu optimieren, um weniger GC-Druck zu erzeugen und einen geringeren Speicherverbrauch zu haben, aber ich denke, wir könnten auch Cloud Foundry verbessern, um dies besser zu handhaben.

Ich habe https://github.com/cloudfoundry/java-buildpack-memory-calculator/issues/24 über die Speicherberechnungsregel angesprochen.

Ein weiterer Punkt: Wenn die Anzahl der Klassen durch Zählen aller .class Dateien in der Anwendung einschließlich ihrer Abhängigkeiten berechnet wird, ist dies keine zuverlässige Informationsquelle für Spring-Anwendungen, die keine sehr feinkörnige JAR-Granularität haben und wird lädt effektiv nur einen kleinen Anteil der Klassen, die auf Spring JARs verfügbar sind.

Noch deutlicher wird das Problem bei den Optimierungen, die wir in Spring Boot 2.1 ausgeliefert haben, und der Optimierung, an der wir gerade für Spring Boot 2.2 arbeiten.

Mein Bauchgefühl ist, dass typische Benutzer wissen, wie viel Xmx Speicher lokal von ihrer Anwendung benötigt wird, und wir sollten diese Informationen vielleicht standardmäßig verwenden.

question

Hilfreichster Kommentar

Es ist möglich, mit weniger als 512 MB zu arbeiten, indem Sie den Speicherrechner konfigurieren.
Folgendes Manifest funktioniert für mich (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.+}]'

Eine Vanilla-Webflux-App läuft tatsächlich mit nur 60 MB RAM.

Ich bin ein großer Fan von Speicherrechnern, da die meisten Entwickler sich nur um die Heap-Größe kümmern und ein unerwartetes OOME (zB Metaspace) bekommen, aber ich stimme zu, dass wir es verbessern könnten.
Die voreingestellte Threadgröße (300?) im Rechner wäre zumindest für webflux zu groß.

Für Anfänger ist es ziemlich schwierig, die Speichergröße anzupassen.
Konfigurationsbeispiele nach Anwendungsfall in README wären sehr hilfreich.

Alle 8 Kommentare

Es ist möglich, mit weniger als 512 MB zu arbeiten, indem Sie den Speicherrechner konfigurieren.
Folgendes Manifest funktioniert für mich (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.+}]'

Eine Vanilla-Webflux-App läuft tatsächlich mit nur 60 MB RAM.

Ich bin ein großer Fan von Speicherrechnern, da die meisten Entwickler sich nur um die Heap-Größe kümmern und ein unerwartetes OOME (zB Metaspace) bekommen, aber ich stimme zu, dass wir es verbessern könnten.
Die voreingestellte Threadgröße (300?) im Rechner wäre zumindest für webflux zu groß.

Für Anfänger ist es ziemlich schwierig, die Speichergröße anzupassen.
Konfigurationsbeispiele nach Anwendungsfall in README wären sehr hilfreich.

@making Ich habe den Titel dieses Problems aktualisiert, um deutlicher zu machen, dass es sich um eine suboptimale Standardkonfiguration für (zumindest) Boot-Anwendungen handelt. Es ist natürlich durchaus möglich, Boot-Anwendungen mit 256M und benutzerdefinierter Konfiguration auszuführen, aber die Standardspeicherkonfiguration scheint mir sehr, sehr weit davon entfernt zu sein, und hier möchte ich, dass wir Fortschritte machen, da sie viele Benutzer betrifft.

Die Anzahl der Threads, die Sie für die WebFlux-Anwendung erwähnen, ist in der Tat ein sehr interessanter Punkt, das Build Pack könnte einen zusätzlichen Mehrwert bieten, indem es erkennt, um welche Art von App es sich handelt. Es kann schwierig sein, da einige MVC-Anwendungen Reactive WebClient , aber ich bin sicher, wir können etwas cleverer und genauer machen.

Ihre benutzerdefinierte Speicherkonfiguration weist IMO darauf hin, dass mit dem automatischen Konfigurationsmechanismus etwas nicht stimmt. Wie in https://github.com/cloudfoundry/java-buildpack-memory-calculator/issues/24 erläutert, wenn ich explizit die Anzahl der Klassen (zwischen 8000 und 10000), die effektiv von Boot-Apps verwendet werden, angebe, ist der generierte Parameter -XX:ReservedCodeCacheSize=240M , wobei Sie -XX:ReservedCodeCacheSize=32M angeben. Dieser Unterschied ist wirklich riesig, könnten wir eine fundiertere Vermutung anstellen?

Auch 8000 oder 10000 sind eine Anzahl von Klassen, die von Boot-Apps effektiv verwendet werden. Wenn das Build Pack dies aus der Anzahl der Klassen in der App + Abhängigkeiten berechnet, neige ich zu der Annahme, dass die Anzahl der für den Speicherrechner angegebenen Klassen künstlich hoch ist (ich muss noch den aktuell geschätzten Wert überprüfen, aber das Build Pack). aufgrund der Natur von Spring Framework JARs.

Ich frage mich auch, ob wir die neuen Containerspeicheroptionen nutzen , die in den neuesten Java 8 und Java 11 verfügbar sind. Sie sind für Docker konzipiert, aber ich denke, wir könnten auch in Cloud Foundry davon profitieren. Ist sich die Java-Laufzeit bewusst, dass wir in Containern ausgeführt werden, obwohl CF Docker nicht verwendet? Nutzen wir Optionen wie -XX:InitialRAMPercentage , -XX:MaxRAMPercentage oder -XX:MinRAMPercentage ?

Es ist ein kniffliges Problem @sdeleuze. Verwendet das Java-Buildpack Java-Standardeinstellungen, von denen wir annehmen, dass einige Überlegungen zur Java-Einstellung angestellt wurden, damit Anwendungen standardmäßig so funktionieren, wie sie es tun, wenn sie nicht in CF ausgeführt werden? Oder ändert das Java-Buildpack die Standardeinstellungen, um die anfängliche Erfahrung zu verbessern, lässt die Benutzer jedoch nach Antworten suchen, wenn die Anwendung nicht wie erwartet und nicht in CF ausgeführt wird?

Heute hat sich das java-buildpack dafür entschieden, Java- und Tomcat-Standardwerte zu verwenden, die auf diese Werte als heute typische Anwendung vertrauen. Ich persönlich mag diesen Ansatz mehr als das Ändern von Java-Standardeinstellungen, die die Anwendung auf eine Weise beeinflussen können, die für den Benutzer nicht sehr sichtbar / explizit ist.

Was die neuen Eigenschaften angeht, so verstehe ich die RAMPercentage Eigenschaften so, dass sie einfach automatisch Heap-Werte basierend auf einem Prozentsatz des verfügbaren RAM festlegen. Keine Gedanken über Nicht-Heap-Speicheranforderungen wie Code-Cache-Größe, Thread-Stack-Größe, Metaspace, GC-Speicher-Overhead usw. Diese Arbeit bleibt dem Benutzer als Übung überlassen, um zu erraten, wie viel Nicht-Heap-Speicher seine Anwendung benötigt. Ich freue mich auf einen Tag, an dem Java einfach alle Speicherpools richtig verwalten kann, um eine Anwendung innerhalb der Speicherbeschränkungen eines Containers zu halten. Aber ich vermute, davon sind wir noch weit entfernt.

Als Randnotiz ist dies die JAVA_OPTS- und jre-Konfiguration, die ich für meine Anwendungen eingestellt habe, die ich mit geringem Speicher stabil sein muss, und Geschwindigkeit ist kein Faktor.

  • Ich habe MaxMetaSize auf einen durch Profiling entdeckten gesetzt.
    JAVA_OPTS
-Xss256K -Xms1M -XX:+UseSerialGC -Djava.compiler=none -XX:ReservedCodeCacheSize=2496k -XX:MaxDirectMemorySize=1M

jre config

  stack_threads: 20
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen