Weitere ähnliche Inhalte Ähnlich wie Best Practices
Java und JVM in Containern (20) Mehr von OPITZ CONSULTING Deutschland (17) Best Practices
Java und JVM in Containern1. © OPITZ CONSULTING 2019
Best Practices
Java und JVM in Containern
BEDCon 2019
Dr. Halil-Cem Gürsoy
OPITZ CONSULTING
@hgutwit
2. © OPITZ CONSULTING 2019
$ whoami | xargs finger
■Senior Solution Architect @ OPITZ CONSULTING
■Seit 20 Jahren in der Java-Welt
■ davor im wissenschaftlichen Umfeld Pascal, C, Lisp, Prolog…
■Verteilte Enterprise Systeme
■ Build, Deployment & Persistenz
■„DevOps“, Infrastructure as Code, Automatisierung…
3. © OPITZ CONSULTING 2019
Eine lange Docker-Reise
■Seit Docker 0.8 (2014) produktiv mit Docker unterwegs
■Build & Testumgebungen für große agile Teams
■ Java/JEE, Testcluster, Datenbanken (NoSQL, RDBMS)
■Continuous Delivery mit Docker
■ Jenkins, Atlassian Bamboo, Docker Swarm, Kubernetes …
■ …aber bekennend "Kubephob" (Konfrontations-Therapie)
4. © OPITZ CONSULTING 2019
Agenda
■Basics, die nichts mit Java/JVM zu tun haben aber wichtig sind
■Java und der Speicher
■Java und die CPU
■Java und Images
■Noch sparsamer, noch schneller
6. © OPITZ CONSULTING 2019
Warum gerade Java?
https://redmonk.com/rstephens/2019/07/18/top20-june-2019/
8. © OPITZ CONSULTING 2019
Base Images
■Ideal-Welt: wir bauen unsere Base-Images FROM scratch
■ kann sehr aufwendig sein, aber Kontrolle über den Inhalt
■Möglichst mit offiziellen Images starten
■Sicherheitsupdates beachten, regelmäßig bauen
9. © OPITZ CONSULTING 2019
Base Images
■möglichst nur eine oder wenige Linux-Distributionen auswählen
■minimales System nutzen:
nur die Pakete, die notwendig sind, nachvollziehbar installieren
■--entrypoint sollte die eigentliche Applikation aufrufen
■… aber auch ein docker run myimage:1 bash erlauben
■Weitere Hinweise im Github-Repo docker-library/official-images
10. © OPITZ CONSULTING 2019https://www.flickr.com/photos/clement127/15914534662
latest is Evil!
11. © OPITZ CONSULTING 2019
Deployment?
■Container sollten nicht wie VM’s „provisioniert“ werden
■Anti-Pattern:
■ Container mit Application Server wird gestartet…
■ …und Applikation wird in den laufenden App-Server deployed
■Reproduzierbar?
14. © OPITZ CONSULTING 2019
Java & glibc
■glibc’s malloc() reserviert 64Mb-Blöcke („Arenas“)
■ Virtual Adress space, u.a. Java Metaspace, Threads usw.
■(Fast) kein Problem bis zur Verwendung von mlockall()
■ „Arenas“ werden dann tatsächlich gemappt
■ElasticSearch, Apache Cassandra (via JNA)
■ Optionale Konfiguration zur Swap-Vermeidung
■Diverse Bug-Einträge, u.a. JDK-8193521
15. © OPITZ CONSULTING 2019
Java & glibc
■MALLOC_ARENA_MAX auf niedrigen Wert setzen
■ Vorsicht wenn SELinux im Einsatz ist!
■ Default: 8 * CPU-Kerne
■Ausprobieren und messen!
■Swap disablen statt JNA/mlockall
17. © OPITZ CONSULTING 2019
Java Heap
docker run -m 256m --rm openjdk:8u111-jdk java -XX:+PrintFlagsFinal -version
|grep -i heapsize | egrep 'Initial|Max'
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-8u111-b14-2~bpo8+1-b14)
OpenJDK 64-Bit Server VM (build 25.111-b14, mixed mode)
uintx InitialHeapSize := 65011712
uintx MaxHeapSize := 1035993088
18. © OPITZ CONSULTING 2019
Java Heap
docker run -m 256m --rm openjdk:8-jdk java -XX:+PrintFlagsFinal -version |
grep -i heapsize | egrep 'Initial|Max'
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)
uintx InitialHeapSize := 8388608
uintx MaxHeapSize := 132120576
19. © OPITZ CONSULTING 2019
Neue Optionen ab 8u191*
■JDK-8196595:
--XX:[+|-]UseContainerSupport (default: +)
■JDK-8186248:
■ -XX:InitialRAMPercentage, -XX:MaxRAMPercentage
-XX:MinRAMPercentage
■ ersetzen:
-XX:InitialRAMFraction, -XX:MaxRAMFraction
-XX:MinRAMFraction
■ Genaue Berechnungsformeln im Code
20. © OPITZ CONSULTING 2019
Min / Max Heap
docker run -m 1024m --rm openjdk:12.0.2-jdk java -XX:+PrintFlagsFinal -
version | grep -E "UseContainerSupport | MaxRAMPercentage | MinRAMPercentage"
double MaxRAMPercentage = 25.000000
double MinRAMPercentage = 50.000000
bool UseContainerSupport = true
docker run -m 1024m --rm openjdk:12.0.2-jdk java -XshowSettings:vm -version
VM settings:
Max. Heap Size (Estimated): 247.50M
Using VM: OpenJDK 64-Bit Server VM
docker run -m 1024m --rm openjdk:12.0.2-jdk java -XX:MaxRAMPercentage=75.0
-XshowSettings:vm -version
VM settings:
Max. Heap Size (Estimated): 742.44M
Using VM: OpenJDK 64-Bit Server VM
22. © OPITZ CONSULTING 2019
CPU-Limits
■Ab Java 9 / 10 werden Docker CPU-Limits berücksichtigt
■ --cpuset-cpus, --cpus / --cpu-quota, --cpu-period,
--cpu-shares
■–XX:PreferContainerQuotaForCPUCount (default true)
■Alternativ/Manuell: –XX:ActiveProcessorCount
23. © OPITZ CONSULTING 2019
CPU-Limits
echo 'Runtime.getRuntime().availableProcessors()' |
docker run -i --rm openjdk:12.0.2-jdk jshell
jshell> Runtime.getRuntime().availableProcessors()
$1 ==> 4
echo 'Runtime.getRuntime().availableProcessors()' |
docker run --cpus 1 -i --rm openjdk:12.0.2-jdk jshell
jshell> Runtime.getRuntime().availableProcessors()
$1 ==> 1
26. © OPITZ CONSULTING 2019
Java Images
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hellojava 3 7733be0c7852 About a minute ago 390MB
debian stretch-slim 220611111e8c 2 weeks ago 55.3MB
openjdk 12.0.2-jdk e1e07dfba89c 2 weeks ago 470MB
27. © OPITZ CONSULTING 2019
Auf Diät…
■Ab Java 9 haben wir JDK-Module zur Verfügung
■Es sollten nur die benötigten Module der JRE in das Image
■Mit Hilfe von jlink kann eine angepasste JRE erzeugt werden
■ Mit jdeps kann Liste der benötigten Module erzeugt werden
29. © OPITZ CONSULTING 2019
Slim…
docker images | grep hello
hellojava slim-1 0f67adf4b101 5 minutes ago 92.1MB
hellojava 3 7733be0c7852 51 minutes ago 390MB
30. © OPITZ CONSULTING 2019
Da geht noch was!
■Projekt Portola migriert die OpenJDK von glibc auf musl
■musl ist eine schlanke Implementierung der libc für Alpine Linux
■Early Access von OpenJDK für Alpine/musl:
http://jdk.java.net/14/
■Alpine/musl mit java.base ca. 51 Mb!
32. © OPITZ CONSULTING 2019
AppCDS
■In 8u40 als kommerzielles Feature eingeführt
■Option -XX:+UseAppCDS in JDK 11 obsolet erklärt und in 12 entfernt, da
nun „default“
■Interne Repräsentation der Applikations-Klassen in memmory-mapped files
■Schnelleres Laden bei großen Servern/Applikationen und kleineres memory
Footprint
■ Beispiele mit WebLogic usw. ca. 10% - 20% schneller
■ Bei „einfachen“ / kleinen Applikationen kein besonderer Effekt
34. © OPITZ CONSULTING 2019
AOT statt JIT-Compiler
■Ähnlich der AppCDS wird im Vorfeld eine Shared Library erzeugt
■Es erfolgt zur Laufzeit keine Optimierung durch HotSpot
■Macht Sinn bei kurz laufenden Java-Prozessen
■ … z.B. bei Functions mit Java (Fn, OpenFaaS, …)
■Stolperfalle: Shared Library kann sehr groß werden
■ Selektiv die verwendeten Klassen compilieren
36. © OPITZ CONSULTING 2019
GraalVM
■„…is a universal virtual machine for running applications written in
JavaScript, Python, Ruby, R, JVM-based languages like Java, Scala,
Groovy, Kotlin, Clojure, and LLVM-based languages such as C and
C++.“ https://www.graalvm.org
39. © OPITZ CONSULTING 2019
GraalVM
Step 5/8 : RUN native-image HelloJava
---> Running in ca6f04a96def
Build on Server(pid: 32, port: 38449)*
[hellojava:32] classlist: 1,477.66 ms
[hellojava:32] (cap): 890.19 ms
[hellojava:32] setup: 1,932.33 ms
…
[hellojava:32] compile: 6,405.54 ms
[hellojava:32] image: 502.27 ms
[hellojava:32] write: 109.88 ms
[hellojava:32] [total]: 20,302.07 ms
root@b914b8045203:/# ls -lh
total 5.5M
drwxr-xr-x 2 root root 4.0K Aug 12 00:00 bin
drwxr-xr-x 2 root root 4.0K Mar 28 09:12 boot
drwxr-xr-x 5 root root 360 Sep 4 20:30 dev
drwxr-xr-x 1 root root 4.0K Sep 4 20:30 etc
-rwxr-xr-x 1 root root 5.4M Sep 4 20:24 hellojava
40. © OPITZ CONSULTING 2019
GraalVM
■Aktuell noch „Probleme“ mit Reflection und Proxies
■"Spring Framework provides initial support for GraalVM native
images as of 5.1.“
■Andere Frameworks wie Micronaut sind da besser vorbereitet
42. © OPITZ CONSULTING 2019
https://www.flickr.com/photos/tcmorgan/7372944070
@OC_WIRE
OPITZCONSULTING
opitzconsulting
opitz-consulting-bcb8-1009116
WWW.OPITZ-CONSULTING.COM