[DOCKER] Unterschiede im Standardverhalten der Speicher- und CPU-Erkennung auf Kubernetes (GKE) für jede Java-Version

Einführung

Auch in Java 8 [Oracle Blogs Japanese Summary- [Java] Java SE-Unterstützung für Docker-CPU- und Speicherbeschränkungen](https://orablogs-jp.blogspot.com/2017/05/java-se-support-for-docker-cpu- and.html) Können Sie aus dem Artikel nach 8u131 container.resource.limit.cpu und container.resource.limit.memory bis zu einem gewissen Grad sehen und etwas Gutes tun? Ich dachte, dass es kein gutes Verhalten war, also untersuchte ich die CPU-Erkennung durch Java8, Java10, Java11 (EA) beim Ausführen mit Kubernetes und den Teil, um die Speichergröße zu sichern.

Ändert sich insbesondere das Verhalten von Runtime # availableProcessors, das sich auf die parallele Ausführung von GC (Anzahl der Threads) und die Anzahl der Pools verschiedener paralleler Threads auswirkt, je nach Version? Ist das Teil https://bugs.openjdk.java.net/browse/JDK-8140793 Selbst wenn Sie es sich ansehen, zum 31. Juli 2018 wurde die feste Version noch nicht veröffentlicht, daher habe ich mich gefragt, ob eine Version ordnungsgemäß funktionieren würde.

Fazit

Voraussetzung Java-Anwendung

Überprüfen Sie die Metrikinformationen, wenn Sie die entsprechende Spring Boot-Anwendung ausführen, und die Informationen, wenn Sie "java -XX: + PrintGCDetails -XX: + PrintFlagsFinal -XX: + UnlockExperimentalVMOptions" auf dem Container ausführen.

Spring Boot-Anwendung https://github.com/h-r-k-matsumoto/spring-boot-sample Basierend auf wurde jedes wie folgt geändert. Darüber hinaus ist die Ressourcenzuweisung an den Cointainer wie folgt.

020_deployments.yml


        resources:
          requests:
            cpu: 150m
            memory: 512Mi
          limits:
            cpu: 900m
            memory: 512Mi

Der vollständige Text der Bereitstellungen https://github.com/h-r-k-matsumoto/spring-boot-sample/blob/master/kubernetes/020_deployments.yml ist.

java8 (no cgroup option) Ändern Sie das Bild von pom.xml in das folgende. Insbesondere steuern Java-Optionen nichts. Übernehmen Sie die Standardeinstellung.

pom.xml


  <image>openjdk:8u171-jre-alpine</image>

java8 Ändern Sie das Bild von pom.xml in das folgende.

pom.xml


  <image>openjdk:8u171-jre-alpine</image>

Fügen Sie außerdem die folgende Option jvmFlag hinzu. Der Punkt ist "UseCGroupMemoryLimitForHeap". Der Rest ... trage ich immer, wenn ich in einer Docker-Umgebung laufe.

pom.xml


  <jvmFlag>-XX:+UnlockExperimentalVMOptions</jvmFlag>
  <jvmFlag>-XX:+UseCGroupMemoryLimitForHeap</jvmFlag>
  <jvmFlag>-XX:ParallelGCThreads=1</jvmFlag>
  <jvmFlag>-XX:CICompilerCount=2</jvmFlag>
  <jvmFlag>-Djava.util.concurrent.ForkJoinPool.common.parallelism=1</jvmFlag>

java10 Ändern Sie das Bild von pom.xml in das folgende. Es sind keine Optionen angegeben.

pom.xml


  <image>openjdk:10-jre-slim</image>

java11 (ea) Ändern Sie das Bild von pom.xml in das folgende. Es sind keine Optionen angegeben.

pom.xml


  <image>openjdk:11-jre-slim</image>

Messinhalt

Spring Boot Actuator-Metriken

PrintFlagsFinal


 kubectl exec {pod-name} -- java -XX:+PrintGCDetails -XX:+PrintFlagsFinal -XX:+UnlockExperimentalVMOptions

Verwenden Sie die durch Ausführen erhaltenen Informationen.

Spring Boot Actuator - metrics

system.cpu.count http://pod-ip:port/actuator/metrics/system.cpu.count Hol es dir mit. Dies ist das Ausführungsergebnis von Runtime # availableProcessors. Die Quelle ist [Mikrometer --ProcessorMetrics.java](https://github.com/micrometer-metrics/micrometer/blob/35890bdc64614c24a8117099b0dcdaa003eab798/micrometer-core/src/main/java/io/micrometer/system/instrument/instrument/ ProcessorMetrics.java # L83).

jvm.memory.max (heap) http://pod-ip-port/actuator/metrics/jvm.memory.max?tag=area:heap Hol es dir mit. Die maximale Größe des Heap-Bereichs. Die Quelle ist Mikrometer - JvmMemoryMetrics.java /JvmMemoryMetrics.java#L77-L96). Dies ist das Ergebnis von MemoryUsage # getMax.

PrintFlagsFinal Ergebnis

MaxHeapSize Die Größe des maximalen Heap-Verwaltungsbereichs. Es sollte dasselbe sein wie [jvm.memory.max](# jvm.memory.max? Tag = area: heap).

UseParallelGC Gibt an, ob GC parallel ausgeführt werden soll. Referenz: https://docs.oracle.com/javase/jp/8/docs/technotes/guides/vm/gctuning/collectors.html

ParallelGCThreads Die Anzahl der Threads für die parallele GC.

Messergebnis

Die Spezifikation des auszuführenden Knotens ist vCPUx2 und Speicher 7,5 GB.

java version system.cpu.count jvm.memory.max(heap):MiB MaxHeapSize:MiB UseParallelGC ParallelGCThreads
java 11(ea) 1 123.75 128.00 false 0
java 10 1 123.75 128.00 false 0
java 8 2 120.00 128.00 true 2
java 8 (no cgroup option) 2 1,857.00 1,870.00 true 2

Sofern keine Option angegeben ist, werden Java11 und Java10 korrekt aus der den Containern zugewiesenen Speichergröße "512Mi" und MaxRAMFraction = 4 berechnet, also 512/4 = 128. Auch die CPU ist auf 900 m eingestellt, wird aber als ein Kern beurteilt. java11 und java10 scheinen auf dem Container korrekt zu funktionieren, ohne Xmx oder Xms anzugeben.

Im Fall von Java8 können Sie den Speicher steuern. In Bezug auf die Anzahl der CPUs scheint es jedoch nicht möglich zu sein, gute Ergebnisse zu erzielen. Es scheint besser, den Teil festzulegen, der aus "Runtime # availableProcessors" berechnet wird und jedes Mal Ressourcen in den Systemeigenschaften usw. sichert.

Es ist mir egal, ob es einen kleinen Unterschied zwischen jvm.memory.max (Heap) und MaxHeapSize gibt! Bitte weisen Sie darauf hin, wenn Sie sagen "Es ist besser, eine solche Option anzugeben" oder "Dies ist falsch".

Referenz

--FookJoinPool und Anzahl der Poolspezifikationen: https://docs.oracle.com/javase/jp/8/docs/api/java/util/concurrent/ForkJoinPool.html#ForkJoinPool--

Recommended Posts

Unterschiede im Standardverhalten der Speicher- und CPU-Erkennung auf Kubernetes (GKE) für jede Java-Version
Links für jede Version (japanische Version) der Java SE-API
[Für Anfänger] Erläuterung von Klassen, Instanzen und Statik in Java
[Java] Machen Sie die Variablen der erweiterten for-Anweisung und für jede Anweisung unveränderlich
Definieren Sie abstrakte Methoden in Java enum und schreiben Sie deren Verhalten
Ein Hinweis zu den Unterschieden zwischen Schnittstellen und abstrakten Klassen in Java
Speichermessung von Java-Apps unter Windows
Unerwartetes Verhalten der Standardnachricht in org.springframework.context.MessageSource.getMessage ()
Diskriminierung von Enum in Java 7 und höher