Prise en charge de Java 10 Docker

Avec la sortie de Java 10, qui est une étape importante en termes de chiffres, je pense que la communauté Java profite du printemps après un long moment et est effrayée par la course de mise à jour à venir.

Les nouvelles fonctionnalités de Java 10 ont été introduites dans divers blogs, mais j'ai fait une petite recherche sur le support Docker qui m'intéressait personnellement.

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

A propos de Docker, il y a environ 3 correspondances, mais voici ce qui vous intéresse.

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.

Lorsque la JVM s'exécute dans le conteneur Doocker, elle examinait les paramètres du système d'exploitation sans regarder les paramètres du conteneur Docker, mais Java 10 a amélioré cela. J'ai donc créé à la hâte une image Docker avec Java 10 et l'ai essayée pour voir à quoi elle ressemblait réellement.

L'image Docker a été créée avec ce script. https://gist.github.com/c9katayama/634b14ea65f3910448e0c93b4637a1c1 Vous pouvez créer une image Ubuntu Docker en téléchargeant le script ci-dessus, en définissant le nom d'utilisateur dockerhub de manière appropriée, puis en exécutant la version Oracle JDK Linux tar.gz dans le même dossier.

Rapport sur le nombre de processeurs

J'ai également créé des images Java8 (162) et Java9 (9.0.4) à des fins de comparaison. L'environnement d'exécution est Amazon Linux 2017.09 et l'instance EC2 est m4.xlarge (4CPU / mem 16G).

Java8 J'ai exécuté le script suivant.

//démarrer le conteneur Docker
docker run -it c9katayama/java8:162

//implémentation du code java
echo 'public class T{ public static void main(String[] args){ System.out.println("CPU:"+Runtime.getRuntime().availableProcessors()); }}' > T.java

//Compiler et exécuter
javac -cp . T.java && java -cp . T

//résultat
CPU:4

En Java8, lorsque le nombre de processeurs n'était pas spécifié dans le conteneur Docker, 4 ce qui correspond au nombre d'instances pouvait être obtenu. Ensuite, essayez de définir le nombre de processeurs sur 1 lors du démarrage du conteneur Docker (pour être exact, attribuez le deuxième processeur).

//démarrer le conteneur Docker
docker run --cpuset-cpus 1 -it c9katayama/java8:162

//implémentation et exécution de code java (omis)

//résultat
CPU:1

De manière inattendue, j'ai pu obtenir le nombre correct de processeurs alloués au conteneur Docker. Java9 Vient ensuite Java 9. Vous pouvez utiliser JShell à partir de Java9, alors utilisez ceci.

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

Cela a 4 processeurs sans aucun problème. Ensuite, essayez d'allouer le processeur

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

Encore une fois, contrairement aux attentes, j'ai obtenu le nombre correct de processeurs.

Java10 Java 10 est mon préféré, mais comme il l'a été,

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

était. Donc, d'après ce que j'ai vérifié, l'option --cpuset-cpus semble fonctionner à partir de Java8, donc

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

Un code comme celui-ci ne changera probablement pas son comportement.

option cpus (note supplémentaire)

Depuis Docker1.13, il semble y avoir une option appelée -cpus, et j'ai également vérifié cela.

Java8

docker run --cpus 1.0 -it c9katayama/java8:162
//réduction
CPU:4

Java9

docker run --cpus 1.0 -it c9katayama/java9:9.0.4
//réduction
CPU:4

Java10

docker run --cpus 1.0 -it c9katayama/java10:10
//réduction
CPU:1

En ce qui concerne l'option --cpus, il semble que Java 9 n'a pas été pris en charge correctement, et dans Java 10, celui attribué au conteneur Docker peut être pris correctement.

Rapport sur la quantité de mémoire

Ensuite, vérifions la quantité de mémoire. La méthode à utiliser est

Runtime.getRuntime().maxMemory();

est. Par souci de clarté, nous résumerons avec / sans spécification de quantité de mémoire.

Aucune quantité de mémoire spécifiée

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

Il semble que la valeur par défaut (1/4 de la quantité de mémoire du système d'exploitation) soit définie pour Java8, 9 et 10 en fonction de la quantité de mémoire du système d'exploitation, ce qui est comme prévu (je crains que Java8 soit un peu petit). )

Avec la quantité de mémoire spécifiée

Ensuite, essayez de spécifier la spécification de la mémoire (512 Mo). 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 //Décroît

Java8 et Java9 passent avec brio les paramètres du conteneur Docker, mais Java10 semble définir la quantité de mémoire maximale en fonction des spécifications du conteneur Docker.

À propos de l'impact

D'après ce que j'ai vérifié, il ne semble y avoir aucun problème avec le processeur (du moins pour l'option --cpuset-cpus), mais l'option --cpus semble être mieux examinée car elle se comporte différemment. Surtout lors de l'utilisation de paralellStream (), le nombre de threads utilisés dépend du nombre de processeurs, ce qui peut affecter les performances.

En ce qui concerne la mémoire, il peut y avoir un problème dans le cas où 1. la quantité de mémoire a été spécifiée dans le conteneur Docker 2. JavaVM n'a pas d'option de mémoire et semble avoir bien fonctionné jusqu'à présent.

J'ai demandé à @sugarlife (https://twitter.com/sugarlife) de me dire qu'il existe une option JVM (-XX: -UseContainerSupport) qui élimine ce comportement. https://twitter.com/sugarlife/status/976355508343881729

Lorsque je l'ai effectivement transmis à la JVM, il est revenu au comportement avant Java 9.

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  //Exécuter avec des options
MEM:4014M

Dans tous les cas, je pense qu'il est normal de revoir la zone mémoire une fois dans Java 10.

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

Recommended Posts

Prise en charge de Java 10 Docker
À propos de Docker
À propos de l'interface Java
[Java] À propos des fonctionnalités de Java 12
Prise en charge de SonarQube Java 11
[Java] À propos des tableaux
Période de support Java
Quelque chose à propos de java
À propos des fonctionnalités Java
À propos des threads Java
Période de support Java8, 9, 10
Interface [Java]
À propos de la classe Java
À propos des tableaux Java
À propos de l'héritage Java
À propos de l'interface, interface java
/ n \ n docker java
À propos de la capacité de Docker
À propos de Java Var
À propos de Java Literal
À propos des commandes Java
À propos de la sortie du journal Java
À propos de l'interface fonctionnelle Java
Java, à propos d'un tableau à deux dimensions
Une histoire sur la prise en charge de Java 11 pour les services Web
À propos de [Java] [StreamAPI] allMatch ()
À propos de la classe Java StringBuilder
[Java] À propos de la classe Singleton
À propos de la liaison de méthode Java
Découvrez Docker
[Java] À propos des classes anonymes
A propos des méthodes de fractionnement (Java)
[Java Silver] À propos de l'initialisation
A propos de la liste des baies Java
À propos de l'héritage (Java Silver)
À propos de la classe Java String
À propos des modificateurs d'accès Java
À propos des expressions Java lambda
Résumé personnel sur Java
Histoire de support Java 9+ de Lombok
Tout sur la programmation Java
Résumé du support Java 2018
À propos de la classe abstraite de Java
Remarques sur Java GC
Ce que j'ai recherché sur Java 8
À propos des instances Java
Ce que j'ai recherché sur Java 6
[Gradle] À propos des tâches du plug-in Java
Oracle Java 8 sur Docker Ubuntu
À propos des instructions de déclaration de variable Java
Ce que j'ai recherché sur Java 9
[Java] À propos de la gestion des exceptions try-catch
À propos des types de chargeur de classe Java
[Java Silver] À propos de la méthode equals
[Java] À propos de String et StringBuilder
À propos de la limite d'extraction Docker Hub
Ce que j'ai recherché sur Java 7
À propos des directives de codage Java d'Alibaba