[JAVA] Referenzinformationen zur Untersuchung und Analyse des Speichernutzungsstatus von Tomcat

Überblick

Selbst in der heutigen Zeit gibt es noch viele Webanwendungen, die Tomcat verwenden. (Es ist keine Kritik, es wird in vielen Diensten verwendet, das Versions-Upgrade wird fortgesetzt und es ist ein Produkt mit vielen Informationen, daher denke ich, dass es ein ausgezeichneter Anwendungsserver ist.)

Wenn das Entwicklungsunternehmen die Umgebung erstellt, das in Java integrierte System auf dem Server bereitstellt und es eine Weile betreibt, können unvermeidlich Probleme hinsichtlich der Leistung auftreten.

Zum Beispiel ist es gut, Protokolle auszugeben, aber da Rotations- und Dateizerstörungszyklus nicht berücksichtigt werden, wird der Speicher unter Druck gesetzt, und plötzlich fallen Stein und Server aus, und die Verwendung des Heapspeichers steigt allmählich an. Dann stirbt Tomcat aufgrund von OutOfMemoryError usw., und selbst wenn es nicht stirbt, verschlechtert sich die Systemreaktion und es treten Probleme auf, und verschiedene andere Dinge treten auf.

Wenn Sie feststellen, dass Sie Ihren Speicherplatz belasten, löschen Sie häufig Dateien, die Sie für unnötig und ** vorübergehend ** und ** wieder dauerhaft ** halten.

Wenn die Reaktion des Systems schlecht ist und es den Anschein hat, dass der Speicher nach einer leichten Untersuchung die Ursache ist, starten Sie Tomcat und ** vorläufigen Support ** und ** permanenten Support neu, wenn die geschäftlichen Auswirkungen groß sind, wenn sie nicht sofort behoben werden. Die Ursachenuntersuchung für ** soll so etwas wie "Wenn Sie versuchen, sie in den magischen Worten der Entwicklungsfirma wiederzugeben" sein, werde ich sie zu diesem Zeitpunkt untersuchen ", und" Permanente Korrespondenz "wird nicht für immer kommen .. (Es ist eine persönliche Erfahrung und gilt nicht für die ganze Welt.)

Ich habe lange Zeit so etwas wie ein Murren erwähnt, aber die Analyse der Speichernutzung ist möglicherweise erst bekannt, wenn das eigentliche Problem auftritt, und die Situation ist auch in der Produktionsumgebung und der Entwicklungsumgebung der Entwicklungsfirma. Ich verstehe, dass es schwierig zu reproduzieren ist, weil es anders ist. Die derzeitige Situation besteht darin, dass Wartungsverträge von Anwenderunternehmen nur ungern eingegrenzt werden, und es ist keine Situation, in der zeitaufwändige Forschungsarbeiten durchgeführt werden können.

In diesem Fall sollten die Benutzerunternehmen selbst nachforschen. In diesem Sinne verlasse ich diesen Artikel mit der Absicht, meine eigenen Methoden zur Untersuchung und Analyse zusammenzufassen.

So überprüfen Sie den Status des von Tomcat verwendeten Speichers

So überprüfen Sie die PID von Tomcat

In diesem Artikel werde ich verschiedene Befehle verwenden und Nachforschungen anstellen, aber manchmal muss ich die PID von Tomcat im Voraus kennen. Es gibt verschiedene Möglichkeiten, die PID zu überprüfen, und Sie können sie mit dem folgenden Befehl überprüfen.

Wenn der einzige Prozess, der Java verwendet, Tomcat ist, können Sie dies mit dem Befehl pidof überprüfen.

# pidof java
3344

Wenn Sie nicht sicher sind, ob es sich nur um Tomcat handelt, sollten Sie "jcmd" verwenden, um es aufzulisten und die Tomcat-PID zu bestimmen.

# jcmd -l
3344 org.apache.catalina.startup.Bootstrap-Start ← Dies ist die PID von Tomcat
4894 jdk.jcmd/sun.tools.jcmd.JCmd -l

Überprüfen Sie die Speichernutzung mit dem Befehl CentOS top

Geben Sie die PID von Tomcat an und überprüfen Sie den Nutzungsstatus, z. B. den Speicher, mit dem Befehl top.

# top -p 3344
top - 11:22:30 up 23 min,  1 user,  load average: 0.00, 0.00, 0.00
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3939.0 total,   3295.9 free,    273.2 used,    369.9 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   3445.0 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                           
 3344 root      20   0 4204172 190864  28536 S   0.0   4.7   0:03.04 java        

Überprüfen Sie die JVM-Startparameter (optional) mit jcmd

In den Tomcat-Startoptionen (JVM-Startoptionen) können Sie "-Xms", "-Xmx" usw. angeben und die von Tomcat verwendete Speichergröße festlegen.

Als Einstellmethode

--Stellen Sie das ~ / bash_profile des Tomcat-Benutzers ein, um die Umgebungsvariable CATALINA_OPTS zu exportieren

Wenn es keine Tomcat-Umgebungskonstruktionsprozedur und -materialien, mit Ansible erstellte Skripte usw. gibt, Manchmal ist es schwierig zu überprüfen, was gestartet werden soll. (Besonders wenn Sie die Entwicklungsfirma bitten, die Umgebung zu erstellen, zu entwickeln und freizugeben und den Server als Benutzerfirma zu pflegen, ist dies besonders problematisch.)

In einem solchen Fall können Sie mit jcmd überprüfen, welche Art von JVM-Option der derzeit ausgeführte Tomcat derzeit ausführt.

Sie benötigen Ihre Tomcat-PID im Voraus, um dies zu überprüfen.

# jcmd -l
899 org.apache.catalina.startup.Bootstrap start
4894 jdk.jcmd/sun.tools.jcmd.JCmd -l

# jcmd 899 VM.flags
899:
-XX:CICompilerCount=2 -XX:InitialHeapSize=62914560 -XX:MaxHeapSize=991952896 -XX:MaxNewSize=330301440 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=20971520 -XX:OldSize=41943040 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC

Es ist möglich zu überprüfen, wie die Parametereinstellungen wie oben beschrieben sind, z. B. "-XX: MaxHeapSize", das "-Xmx" entspricht.

Holen Sie sich einen Tomcat-Heap-Dump

Ein Heap-Dump ist wie ein Snapshot-Protokoll der Java-Speichernutzung. Wenn Sie einen Heap-Dump abrufen und analysieren, können Sie irgendwie verstehen, wie Java Speicher verwendet. Hier wird mit jcmd ein Heap-Dump erfasst, der von Java 7 aus verwendet werden kann.

# jcmd -l
899 org.apache.catalina.startup.Bootstrap start
4894 jdk.jcmd/sun.tools.jcmd.JCmd -l

# jcmd 899 GC.heap_dump /var/log/heapdump/heapdmp.hprof
899:
Heap dump file created

# ls
heapdmp.hprof

Analysieren Sie Heap-Dumps mit Java Visual VM-Tools

Überprüfen Sie den von jcmd erfassten Heap-Dump mit einem Tool namens Java Visual VM. Die Analyse erfolgt in der lokalen PC-Umgebung (Umgebung mit GUI), JRE muss jedoch im Voraus installiert werden.

In meiner Umgebung wurde Java 1.8 eingerichtet und der Pfad war vorhanden.

$ java -version
java version "1.8.0_241"
Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
Java HotSpot(TM) 64-Bit Server VM (build 25.241-b07, mixed mode)

Führen Sie in dieser Umgebung den folgenden Befehl aus, um das Java Visual VM-Tool zu starten.

$ jvisualvm

Geben Sie die von Open File erhaltene Heap-Dump-Datei an und öffnen Sie sie.

スクリーンショット 2020-10-29 7.43.33.png

スクリーンショット 2020-10-29 7.43.40.png

Es scheint, dass Sie überprüfen können, ob zusätzliche Objekte aus dem Heap-Dump erstellt werden. Meine Erwartung war jedoch, dass es schön wäre, den Status der Speichernutzung und die Freigabe des Speichers durch GC in der Grafik zu sehen. Daher kann der Speicherauslastungsstatus nur von diesem Heap-Dump erfasst werden, die Ursache kann identifiziert werden und er kann als Auslöser für eine permanente Reaktion verwendet werden. Ich dachte, es wäre schwierig.

Analyse mit Java Monitoring & Management Console

Es scheint möglich zu sein, den Status der Speichernutzung usw. mit einem Tool namens JConsole grafisch zu analysieren. https://docs.oracle.com/javase/jp/8/docs/technotes/guides/management/jconsole.html

Hier wird die JVM von JConsole über den JMX-Agenten für Tomcat überwacht, der auf dem CentOS-Server vom lokalen PC aus erstellt wurde.

JMX-bezogene Einstellungen zu den JVM-Startoptionen von Tomcat hinzugefügt

Ich denke, es gibt verschiedene Möglichkeiten, die JVM-Startoption von Tomcat anzugeben, aber hier fügen Sie die Einstellung mit der in setenv.sh angegebenen Methode hinzu.

{tomcat-root}/bin/setenv.sh


#!/bin/sh

JAVA_OPTS="-server -Xms512M -Xmx2G -Dspring.profiles.active=production -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.33.10"

Dcom.sun.management.jmxremote.port gibt den vom JMX-Agenten verwendeten Port an. Angenommen, Tomcat verwendet Port 8080, habe ich einen anderen Port angegeben.

Darüber hinaus wird der Parameter "Djava.rmi.server.hostname" angegeben, um vom lokalen PC aus remote auf den Tomcat-Server zuzugreifen und eine JVM-Überwachung durchzuführen. Wenn Sie diesen Parameter nicht angeben, wird beim Versuch, eine Verbindung zu "192.168.33.10: 8888" in JConsole herzustellen, die Meldung "Sichere Verbindung fehlgeschlagen. Möchten Sie es unsicher wiederholen?" Angezeigt. Ich habe es versucht, konnte aber keine Verbindung herstellen. Seien Sie also vorsichtig, wenn Sie Fernzugriff benötigen.

Überprüfen Sie nach den obigen Einstellungen und dem Neustart von Tomcat, ob der angegebene Port "8888" ordnungsgemäß abgehört wird.

# systemctl restart tomcat

# ss -antup | grep 8888
tcp   LISTEN  0       50                         *:8888                *:*       users:(("java",pid=4211,fd=17))  

# ps -ef | grep jmx

Starten Sie die Java Monitoring & Management Console (JConsole) und führen Sie die JVM-Überwachung durch

Starten Sie das jconsole-Tool mit dem folgenden Befehl und überprüfen Sie die Speichernutzung. Der folgende Befehl wird vom lokalen PC ausgeführt. Bitte beachten Sie, dass der Befehl jconsole nur ausgeführt werden kann, wenn die JRE vorinstalliert ist und der Pfad korrekt ist.

jconsole 192.168.33.10:8888

Die Registerkarte Übersicht bietet eine grafische Ansicht darüber, wie Speicher, Threads, Klassen, CPU-Auslastung usw. im Laufe der Zeit verwendet werden. Es scheint, dass die Informationen auf dieser Registerkarte "Übersicht" für die Analyse ausreichen. Überprüfen wir jedoch den Inhalt der anderen Registerkarten.

スクリーンショット 2020-10-29 20.40.57.png

スクリーンショット 2020-10-29 20.41.51.png

スクリーンショット 2020-10-29 20.42.34.png

スクリーンショット 2020-10-29 20.42.56.png

スクリーンショット 2020-10-29 20.43.21.png

Analyse mit GC Viewer

GCViewer https://github.com/chewiebug/GCViewer/wiki/Changelog

Die JConsole-Analyse konnte bestätigen, wie oft GC auftrat, wusste jedoch nicht, wann GC auftrat. Holen Sie sich also das GC-Protokoll und überprüfen Sie mit GCViewer die Häufigkeit des Auftretens von GC und die von GC freigegebene Speichermenge sowie den Status der Speichernutzung.

Holen Sie sich das GC-Protokoll

Um das GC-Protokoll abzurufen, legen Sie die JVM-Optionen von Tomcat wie folgt fest:

{tomcat-root}/bin/setenv.sh


JAVA_OPTS="-server -Xms512M -Xmx2G -Dspring.profiles.active=production -verbose:gc -Xlog:gc*=info:file=/var/log/gclog/gc.log:time,uptime,level,tags:filecount=1,filesize=10m"

Starten Sie nach Abschluss der obigen Einstellungen den Tomcat-Dienst neu und lassen Sie ihn eine Weile stehen. (Lassen Sie die Web-App auf Tomcat eine Weile funktionieren.)

Wenn ich das erfasste Protokoll mit gcviewer anzeige, sieht es folgendermaßen aus.

スクリーンショット 2020-10-31 10.52.12.png

Beschreibung der GC Viewer-Diagrammlegende

Es wird auf verschiedene Arten angezeigt und ich bin mir nicht sicher, welche Farbe welche Rolle spielt. Sie können in der Menüansicht anzeigen / ausblenden, wie jede Farbe aussieht.

スクリーンショット 2020-10-31 10.53.00.png

Die Auswirkungen der einzelnen werden im Folgenden kurz erläutert.

Probe zeigt nur Total Heap und Full GC

Wenn Sie weiterhin die angegebene Größe von -Xmx erreichen, können Sie feststellen, dass Full GC häufig auftritt. Wenn die Größe des Heaps nach der vollständigen GC abnimmt, scheint die Häufigkeit der vollständigen GC tendenziell abzunehmen.

スクリーンショット 2020-10-31 11.03.46.png

Es gab jedoch eine Zeit, in der eine vollständige GC nicht häufig auftrat und die obere Grenzgröße auch dann erhalten blieb, wenn die obere Grenzgröße feststeckte.

スクリーンショット 2020-10-31 11.05.00.png

Beispiel, das die Aufteilung des Haufens (junger Bereich und alter Bereich) und des FullGC zeigt

Anstelle von Total Heap werden der Young-Bereich (Young Generation: Orange) und der Old-Bereich (Tenured Generation: Pink) als Aufschlüsselung angezeigt, und der Speichernutzungsstatus wird in Kombination mit Full GC analysiert.

スクリーンショット 2020-10-31 11.16.29.png

Die Geschichte, dass sich der JVM-Parameter zum Abrufen des GC-Protokolls seit Java 9 geändert hat und Probleme bereitet hat

Als ich Google durchsuchte und die JVM-Option aktivierte, um das GC-Protokoll abzurufen, war dies die folgende Option, also habe ich es versucht.

{tomcat-root}/bin/setenv.sh


JAVA_OPTS="-server -Xms512M -Xmx2G -Dspring.profiles.active=production -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/gclog/gc.log"

Nach Abschluss der obigen Einstellungen funktionierte die mit Tomcat erstellte Webanwendung nicht mehr, als ich den Tomcat-Dienst neu startete. Als ich untersuchte, warum es nicht mehr funktionierte, fand ich den folgenden Fehler.

{tomcat-root}/logs/catalina.out


Unrecognized VM option 'PrintGCDateStamps'
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
NOTE: Picked up JDK_JAVA_OPTIONS:  --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAM

Anscheinend sind einige JVM-Parameter in Java 9 oder höher nicht mehr verfügbar (JVM kann bei Verwendung nicht gestartet werden). Daher müssen Sie den nicht verfügbaren Parameter durch einen anderen Parameter ersetzen.

https://docs.oracle.com/javase/9/tools/java.htm#JSWOR624

Informationen zu Ersatzparametern, die als Referenz verwendet werden können, finden Sie im Abschnitt "Konvertieren von GC-Protokollierungsflags in Xlog" auf dieser Site. Es werden jedoch nicht alle Parameter eins zu eins ersetzt, was etwas verwirrend ist.

Beispiele für spezifische Speicheranalysen und -überlegungen

Die Speichernutzung des Heap-Bereichs bleibt die ganze Zeit an der Decke hängen

In der folgenden Grafik ist die Speichernutzung seit einiger Zeit nicht mehr auf etwa 1,4 GB gesunken.

スクリーンショット 2020-10-29 20.47.32.png

Wenn Sie sich den Thread-Status um 20:41 ansehen, als die Speichernutzung plötzlich zunahm, können Sie sehen, dass die Anzahl der Threads ungefähr zur gleichen Zeit ihren Höhepunkt erreichte. Da jedoch die Anzahl der Thread-Ausführungen innerhalb weniger Minuten die Untergrenze erreicht hat, wird spekuliert, dass ein vorübergehender gleichzeitiger häufiger Zugriff aufgetreten sein könnte.

スクリーンショット 2020-10-29 20.49.06.png

Die Tatsache, dass sich die Heap-Speichernutzung auch nach dem Absinken der Anzahl der Threads überhaupt nicht verbessert hat, bedeutet, dass möglicherweise Objekte vorhanden sind, die auch bei einem GC nicht zerstört werden.

スクリーンショット 2020-10-29 20.52.29.png

Wenn Sie den Nutzungsstatus wie den Serverspeicher zu diesem Zeitpunkt mit dem Befehl top überprüfen, sieht dies folgendermaßen aus.

# top -p 923

top - 11:53:47 up  1:01,  1 user,  load average: 0.00, 0.03, 0.05
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
top - 11:54:02 up  1:01,  1 user,  load average: 0.00, 0.03, 0.05
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni, 99.3 id,  0.0 wa,  0.3 hi,  0.3 si,  0.0 st
MiB Mem :   3939.0 total,   1342.6 free,   1657.3 used,    939.1 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   2060.3 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                     
  923 root      20   0 4278196   1.5g  31744 S   0.0  39.7   1:09.33 java  

--VIRT Virtual Image. Alle reservierten virtuellen Speicher. Beinhaltet die Nutzung des getauschten Speichers. (Einheit: kb) ―― Da es sich um ungefähr 4 GB handelt, können Sie sehen, dass die Verarbeitung, die den Speicher bis zu 4 GB verwenden musste, einschließlich der ausgetauschten Verarbeitung, für Tomcat erfolgte, das durch Angabe von 2 GB mit -Xmx ausgeführt wurde. --RES Die Größe des verwendeten physischen Speichers, nicht ausgetauscht.

Wenn es sich nur um einen temporären Fokus handelt, müssen Sie den Parameter -Xmx nicht überprüfen. Wenn dies jedoch häufig vorkommt, müssen Sie möglicherweise das maximale Speichervolumen erhöhen.

Hier ist ein Diagramm, in dem sich der Speicherauslastungsstatus sofort vor 21:00 Uhr verbessert hat.

スクリーンショット 2020-10-29 21.01.14.png

Das Ergebnis des Befehls top in diesem Zustand

# top -p 923

top - 12:04:03 up  1:11,  1 user,  load average: 0.09, 0.04, 0.01
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3939.0 total,   1340.3 free,   1659.6 used,    939.1 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   2058.0 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                     
  923 root      20   0 4278196   1.5g  31744 S   0.3  39.8   1:12.06 java    

Insbesondere haben sich die Werte von VIRT, RES, SHR usw. nicht geändert. Daraus können wir ersehen, dass der Befehl top nur den Maximalwert des Speichers sehen kann, der vorübergehend als Snapshot hochgesprungen ist.

Recommended Posts

Referenzinformationen zur Untersuchung und Analyse des Speichernutzungsstatus von Tomcat
Untersuchen Sie die Speichernutzung von Java-Elementen
Vergleichen Sie die Geschwindigkeit der for-Anweisung und der erweiterten for-Anweisung.
[Für Anfänger] DI ~ Die Grundlagen von DI und DI im Frühjahr ~
Befehl zum Überprüfen der Anzahl und des Status von Java-Threads