Java 10 Docker-Unterstützung

Mit der Veröffentlichung von Java 10, einem Meilenstein in Bezug auf die Anzahl, denke ich, dass die Java-Community nach langer Zeit den Frühling genießt und Angst vor dem bevorstehenden Update-Rennen hat.

Die neuen Funktionen von Java 10 wurden in verschiedenen Blogs vorgestellt, aber ich habe ein wenig über die Docker-Unterstützung recherchiert, an der ich persönlich interessiert war.

Java10-Versionshinweis: http://www.oracle.com/technetwork/java/javase/10-relnote-issues-4108729.html

Über Docker gibt es ungefähr 3 Korrespondenzen, aber hier ist, woran Sie interessiert sind.

Improve docker container detection and resource configuration usage
The following changes have been introduced in JDK 10 to improve the execution and configurability of Java running in Docker containers:

JDK-8146115 Improve docker container detection and resource configuration usage
The JVM has been modified to be aware that it is running in a Docker container and will extract container specific configuration information instead of querying the operating system. The information being extracted is the number of CPUs and total memory that have been allocated to the container. The total number of CPUs available to the Java process is calculated from any specified cpu sets, cpu shares or cpu quotas. This support is only available on Linux-based platforms. This new support is enabled by default and can be disabled in the command line with the JVM option:

-XX:-UseContainerSupport

In addition, this change adds a JVM option that provides the ability to specify the number of CPUs that the JVM will use:

-XX:ActiveProcessorCount=count

This count overrides any other automatic CPU detection logic in the JVM.

Wenn die JVM im Doocker-Container ausgeführt wird, wurden früher die Betriebssystemeinstellungen und nicht die Docker-Containereinstellungen überprüft. Java 10 hat dies jedoch verbessert. Also habe ich schnell ein Docker-Image mit Java 10 erstellt und versucht, zu sehen, wie es tatsächlich aussieht.

Das Docker-Image wurde mit diesem Skript erstellt. https://gist.github.com/c9katayama/634b14ea65f3910448e0c93b4637a1c1 Nachdem Sie das obige Skript heruntergeladen und den Benutzernamen von Dockerhub entsprechend festgelegt haben, können Sie ein Docker-Image von Ubuntu erstellen, indem Sie tar.gz für Linux von Oracle JDK im selben Ordner ausführen.

CPU-Zählbericht

Zum Vergleich habe ich auch Java 8 (162) - und Java 9 (9.0.4) -Bilder erstellt. Die Ausführungsumgebung ist Amazon Linux 2017.09 und die EC2-Instanz ist m4.xlarge (4CPU / mem 16G).

Java8 Ich habe das folgende Skript ausgeführt.

//Docker-Container starten
docker run -it c9katayama/java8:162

//Java-Code-Implementierung
echo 'public class T{ public static void main(String[] args){ System.out.println("CPU:"+Runtime.getRuntime().availableProcessors()); }}' > T.java

//Kompilieren und ausführen
javac -cp . T.java && java -cp . T

//Ergebnis
CPU:4

Wenn in Java8 die Anzahl der Prozessoren nicht im Docker-Container angegeben wurde, 4 konnte die Anzahl der Instanzen ermittelt werden. Versuchen Sie als Nächstes, die Anzahl der CPUs beim Starten des Docker-Containers auf 1 zu setzen (um genau zu sein, weisen Sie den zweiten Prozessor zu).

//Docker-Container starten
docker run --cpuset-cpus 1 -it c9katayama/java8:162

//Implementierung und Ausführung von Java-Code (weggelassen)

//Ergebnis
CPU:1

Unerwartet konnte ich die richtige Anzahl von CPUs erhalten, die dem Docker-Container zugewiesen waren. Java9 Als nächstes kommt Java 9. Sie können JShell von Java9 aus verwenden, verwenden Sie dies also.

docker run -it c9katayama/java9:9.0.4
jshell
jshell> System.out.println("CPU:"+Runtime.getRuntime().availableProcessors())
CPU:4

Dies hat 4 CPUs ohne Probleme. Versuchen Sie als Nächstes, die CPU zuzuweisen

docker run --cpuset-cpus 1 -it c9katayama/java9:9.0.4
jshell
jshell> System.out.println("CPU:"+Runtime.getRuntime().availableProcessors())
CPU:1

Entgegen den Erwartungen habe ich wieder die richtige Anzahl von CPUs bekommen.

Java10 Java 10 ist mein Favorit, aber wie es war,

docker run -it c9katayama/java10:10
->CPU:4
docker run  --cpuset-cpus 1 -it c9katayama/java10:10
->CPU:1

war. Soweit ich überprüft habe, scheint die Option --cpuset-cpus von Java8 aus zu funktionieren

int threadNum = Runtime.getRuntime().availableProcessors() /2;

Es ist unwahrscheinlich, dass ein solcher Code sein Verhalten ändert.

CPU-Option (zusätzlicher Hinweis)

Ab Docker1.13 scheint es eine Option namens -cpus zu geben, und ich habe dies auch überprüft.

Java8

docker run --cpus 1.0 -it c9katayama/java8:162
//Kürzung
CPU:4

Java9

docker run --cpus 1.0 -it c9katayama/java9:9.0.4
//Kürzung
CPU:4

Java10

docker run --cpus 1.0 -it c9katayama/java10:10
//Kürzung
CPU:1

In Bezug auf die Option --cpus scheint Java 9 nicht korrekt unterstützt worden zu sein, und in Java 10 kann die dem Docker-Container zugewiesene Option korrekt übernommen werden.

Speichermengenbericht

Als nächstes überprüfen wir die Speichermenge. Die zu verwendende Methode ist

Runtime.getRuntime().maxMemory();

ist. Aus Gründen der Klarheit werden wir mit / ohne Speichermengenangabe zusammenfassen.

Keine Speichermenge angegeben

Java8

docker run -it c9katayama/java8:162
echo 'public class T{ public static void main(String[] args){ System.out.println("MEM:"+Runtime.getRuntime().maxMemory()/1024/1024+"M"); }}' > T.java
javac -cp . T.java && java -cp . T
MEM:3568M

Java9

docker run -it c9katayama/java9:9.0.4
jshell> System.out.println("MEM:"+Runtime.getRuntime().maxMemory()/1024/1024+"M")
MEM:4014M

Java10

docker run -it c9katayama/java10:10
jshell> System.out.println("MEM:"+Runtime.getRuntime().maxMemory()/1024/1024+"M")
MEM:4014M

Es scheint, dass der Standardwert (1/4 der Betriebssystemspeichermenge) für Java8, 9 und 10 basierend auf der Betriebssystemspeichermenge festgelegt wird, was wie erwartet ist (ich mache mir Sorgen, dass Java8 etwas klein ist). )

Mit angegebener Speichermenge

Versuchen Sie als Nächstes, die Speicherspezifikation (512 MB) anzugeben. Java8

docker run -m 512m -it c9katayama/java8:162
echo 'public class T{ public static void main(String[] args){ System.out.println("MEM:"+Runtime.getRuntime().maxMemory()/1024/1024+"M"); }}' > T.java
javac -cp . T.java && java -cp . T
MEM:3568M

Java9

docker run -m 512m -it c9katayama/java9:9.0.4
jshell> System.out.println("MEM:"+Runtime.getRuntime().maxMemory()/1024/1024+"M")
MEM:4014M

Java10

docker run -m 512m -it c9katayama/java10:10
jshell> System.out.println("MEM:"+Runtime.getRuntime().maxMemory()/1024/1024+"M")
MEM:123M //Nimmt ab

Java8 und Java9 durchlaufen die Docker-Containereinstellungen auf brillante Weise, aber Java10 scheint die maximale Speichermenge basierend auf den Docker-Containerspezifikationen festzulegen.

Über die Auswirkungen

Soweit ich überprüft habe, scheint es kein Problem mit der CPU zu geben (zumindest für die Option --cpuset-cpus), aber die Option --cpus scheint besser überprüft zu werden, da sie sich anders verhält. Insbesondere bei Verwendung von paralellStream () hängt die Anzahl der verwendeten Threads von der Anzahl der Prozessoren ab, was die Leistung beeinträchtigen kann.

In Bezug auf den Speicher kann ein Problem auftreten, wenn 1. die Speichermenge im Docker-Container angegeben wurde 2. JavaVM keine Speicheroption hat und bisher anscheinend gut funktioniert hat.

Ich habe @sugarlife (https://twitter.com/sugarlife) gebeten, mir mitzuteilen, dass es eine JVM-Option (-XX: -UseContainerSupport) gibt, die dieses Verhalten beseitigt. https://twitter.com/sugarlife/status/976355508343881729

Als ich es tatsächlich an die JVM übergeben habe, kehrte es zum Verhalten vor Java 9 zurück.

docker run -m 512m -it c9katayama/java10:10
echo 'public class T{ public static void main(String[] args){ System.out.println("MEM:"+Runtime.getRuntime().maxMemory()/1024/1024+"M"); }}' > T.java
javac -cp . T.java 
java -XX:-UseContainerSupport -cp . T  //Mit Optionen ausführen
MEM:4014M

In jedem Fall denke ich, dass es in Ordnung ist, den Speicherbereich einmal in Java 10 zu überprüfen.

Docker-Ressourcenzuweisung: https://docs.docker.com/config/containers/resource_constraints/#configure-the-default-cfs-scheduler

Recommended Posts

Java 10 Docker-Unterstützung
Über Docker
Über die Java-Schnittstelle
[Java] Informationen zu Java 12-Funktionen
Unterstützung für SonarQube Java 11
[Java] Über Arrays
Java-Support-Zeitraum
Etwas über Java
Informationen zu Java-Funktionen
Über Java-Threads
Supportzeitraum für Java8, 9, 10
[Java] -Schnittstelle
Über die Java-Klasse
Informationen zu Java-Arrays
Über Java-Vererbung
Über Schnittstelle, Java-Schnittstelle
/ n \ n Docker Java
Informationen zur Docker-Kapazität
Über Java Var
Über Java Literal
Informationen zu Java-Befehlen
Informationen zur Java-Protokollausgabe
Informationen zur Java-Funktionsschnittstelle
Java, über zweidimensionales Array
Eine Geschichte über die Java 11-Unterstützung für Webdienste
Über [Java] [StreamAPI] allMatch ()
Informationen zur Java StringBuilder-Klasse
[Java] Über Singleton Class
Informationen zur Bindung von Java-Methoden
Informieren Sie sich über Docker
[Java] Über anonyme Klassen
Informationen zu Aufteilungsmethoden (Java)
[Java Silver] Informationen zur Initialisierung
Informationen zur Java-Array-Liste
Informationen zur Vererbung (Java Silver)
Informationen zur Java String-Klasse
Informationen zu Java-Zugriffsmodifikatoren
Über Java-Lambda-Ausdrücke
Persönliche Zusammenfassung über Java
Lomboks Java 9+ Support-Story
Zusammenfassung der Java-Unterstützung 2018
Über die abstrakte Klasse von Java
Hinweise zu Java GC
Was ich über Java 8 recherchiert habe
Über Java-Instanzen
Was ich über Java 6 recherchiert habe
[Gradle] Informationen zu Java-Plug-In-Aufgaben
Oracle Java 8 unter Docker Ubuntu
Informationen zu Java-Variablendeklarationsanweisungen
Was ich über Java 9 recherchiert habe
[Java] Informationen zur Behandlung von Try-Catch-Ausnahmen
Informationen zu Java Class Loader-Typen
[Java Silver] Über gleich Methode
[Java] Über String und StringBuilder
Informationen zum Pull-Limit von Docker Hub
Was ich über Java 7 recherchiert habe
Informationen zu Alibaba Java-Codierungsrichtlinien