Profilerstellung für Java-Code

Auf dieser Seite wird beschrieben, wie Sie Ihre Java-Anwendung so ändern, dass Datenprofile erstellt und an Ihr Google Cloud-Projekt gesendet werden können. Allgemeine Informationen zur Profilerstellung finden Sie unter Konzepte der Profilerstellung.

Profiltypen für Java:

  • CPU-Zeit
  • Heap (erfordert Java 11 oder die App Engine-Standardumgebung, standardmäßig deaktiviert)
  • Echtzeit (für Java 8 in der App Engine-Standardumgebung nicht verfügbar)

Unterstützte Java-Sprachversionen:

  • HotSpot-basierte JVMs (einschließlich Oracle JDK und einiger OpenJDK-Builds) für Java 8, 11 oder höher.

Unterstützte Profiler-Agent-Versionen:

  • Der neueste Release des Agents wird unterstützt. Im Allgemeinen werden Releases, die älter als ein Jahr sind, nicht unterstützt. Wir empfehlen, die neueste veröffentlichte Version des Agents zu verwenden.

Unterstützte Betriebssysteme:

  • Linux: Die Profilerstellung für Java-Anwendungen wird für Linux-Kernel unterstützt, deren Standard-C-Bibliothek mit glibc oder mit musl implementiert wurde. Konfigurationsinformationen zu Linux Alpine-Kernels finden Sie unter Mit Linux Alpine ausführen.

Unterstützte Umgebungen:

Profiler API aktivieren

Sorgen Sie vor Verwendung des Profiler-Agents dafür, dass die zugrunde liegende Profiler API aktiviert ist. Sie können den Status der API prüfen und sie bei Bedarf über die Google Cloud-Befehlszeile oder die Google Cloud Console aktivieren:

gcloud-CLI

  1. Wenn Sie die Google Cloud-Befehlszeile noch nicht auf Ihrer Workstation installiert haben, lesen Sie die Dokumentation zur Google Cloud-Befehlszeile.

  2. Führen Sie dazu diesen Befehl aus:

    gcloud services enable cloudprofiler.googleapis.com
    

Weitere Informationen finden Sie unter gcloud services.

Google Cloud Console

  1. Enable the required API.

    Enable the API

  2. Wenn API aktiviert angezeigt wird, ist die API bereits aktiviert. Falls nicht, klicken Sie auf die Schaltfläche Aktivieren.

Dienstkonto eine IAM-Rolle zuweisen

Wenn Sie Ihre Anwendung auf Google Cloud-Ressourcen bereitstellen, das Standarddienstkonto verwenden und die Rollenzuweisungen für dieses Dienstkonto nicht geändert haben, können Sie diesen Abschnitt überspringen.

In folgenden Fällen müssen Sie dem Dienstkonto die IAM-Rolle Cloud Profiler-Agent (roles/cloudprofiler.agent) zuweisen:

  1. Sie verwenden das Standarddienstkonto, haben aber seine Rollenzuweisungen geändert.
  2. Sie verwenden ein vom Nutzer erstelltes Dienstkonto.
  3. Sie verwenden Workload Identity und gewähren dem Kubernetes-Dienstkonto die Rolle „Cloud Profiler-Agent“.

Sie können einem Dienstkonto eine IAM-Rolle mithilfe der Google Cloud Console oder der Google Cloud CLI zuweisen. Sie können beispielsweise den Befehl gcloud projects add-iam-policy-binding verwenden:

gcloud projects add-iam-policy-binding GCP_PROJECT_ID \
    --member serviceAccount:MY_SVC_ACCT_ID@GCP_PROJECT_ID.iam.gserviceaccount.com \
    --role roles/cloudprofiler.agent

Ersetzen Sie vor dem Ausführen des Befehls Folgendes:

  • GCP_PROJECT_ID: Ihre Projekt-ID.
  • MY_SVC_ACCT_ID: Name Ihres Dienstkontos.

Weitere Informationen finden Sie unter Zugriff auf Projekte, Ordner und Organisationen verwalten.

Profiler-Agent installieren

Compute Engine

  1. Erstellen Sie ein Installationsverzeichnis für den Profiler-Agent, z. B. /opt/cprof:

     sudo mkdir -p /opt/cprof

  2. Laden Sie das Agent-Archiv aus dem Repository storage.googleapis.com herunter und extrahieren Sie es in das Installationsverzeichnis:

    wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz \
    | sudo tar xzv -C /opt/cprof

GKE

Ändern Sie das Dockerfile, um ein Installationsverzeichnis für den Profiler-Agent zu erstellen. Laden Sie dann das Agent-Archiv herunter und extrahieren Sie es in das Installationsverzeichnis.

Linux (glibc-basierte C-Bibliothek):

Verwenden Sie den folgenden Installationsbefehl:

RUN mkdir -p /opt/cprof && \
  wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz \
  | tar xzv -C /opt/cprof

Linux Alpine (musl-basierte C-Bibliothek):

Verwenden Sie den folgenden Installationsbefehl:

wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent_alpine.tar.gz \
| tar xzv -C /opt/cprof

Flexible Umgebung

Wenn Sie das Basis-Image der Java 8-Laufzeit oder der Java 9-/Jetty 9-Laufzeit von Google verwenden, ist der Profiler-Agent vorinstalliert. Sie müssen also keine zusätzlichen Schritte ausführen, um den Agent zu installieren.

Für alle anderen Basis-Images müssen Sie den Agent installieren. Das folgende Dockerfile enthält beispielsweise die Anleitungen zum Verwenden des openjdk:11-slim-Image, um den Profiler-Agent zu installieren. Es definiert auch die Standardparameter, die beim Starten der Anwendung verwendet werden sollen:

FROM openjdk:11-slim

COPY . .
RUN  apt-get update \
     && apt-get install wget \
     && rm -rf /var/lib/apt/lists/*

RUN mkdir -p /opt/cprof && \
    wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz \
    | tar xzv -C /opt/cprof

CMD ["java", "-agentpath:/opt/cprof/profiler_java_agent.so=OPTION1,OPTION2", "-jar", "PATH_TO_YOUR_JAR_FILE"]

Damit Sie dieses Dockerfile mit der flexiblen App Engine-Umgebung verwenden können, müssen Sie Folgendes tun:

  • Ersetzen Sie OPTION1 und OPTION2 durch die Agent-Konfigurationswerte, die für Ihre Anwendung erforderlich sind, sowie PATH_TO_YOUR_JAR_FILE durch den Pfad zu Ihrer JAR-Datei.
  • Speichern Sie das Dockerfile im selben Verzeichnis wie Ihre app.yaml-Datei.
  • Ändern Sie die Datei app.yaml, um eine benutzerdefinierte Laufzeit anzugeben. Weitere Informationen finden Sie unter Benutzerdefinierte Laufzeiten erstellen.

Standardumgebung

Wenn Sie die Java-Laufzeitumgebung verwenden, ist der Profiler-Agent vorinstalliert. Sie müssen also keine zusätzlichen Schritte ausführen, um den Agent zu installieren. Bei Java-Version 11 und höher ist er unter /opt/cprof vorinstalliert.

Außerhalb von Google Cloud

  1. Erstellen Sie ein Installationsverzeichnis für den Profiler-Agent, z. B. /opt/cprof:

     sudo mkdir -p /opt/cprof

  2. Laden Sie das Agent-Archiv aus dem Repository storage.googleapis.com herunter und extrahieren Sie es in das Installationsverzeichnis:

    wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz \
    | sudo tar xzv -C /opt/cprof

Führen Sie den folgenden Befehl aus, um alle zum Download verfügbaren Versionen des Agents aufzulisten:

gcloud storage ls gs://cloud-profiler/java/cloud-profiler-*

Die Befehlsantwort sieht in etwa so aus:

gs://cloud-profiler/java/cloud-profiler-java-agent_20191014_RC00.tar.gz
gs://cloud-profiler/java/cloud-profiler-java-agent_20191021_RC00.tar.gz
gs://cloud-profiler/java/cloud-profiler-java-agent_20191028_RC00.tar.gz

Wenn Sie eine bestimmte Version des Agents herunterladen möchten, übergeben Sie dessen URL im Downloadbefehl. Wenn Sie beispielsweise den am 28. Oktober 2019 erstellten Agent herunterladen möchten, verwenden Sie die folgende Anweisung:

wget -q -O- https://storage.googleapis.com/cloud-profiler/java/cloud-profiler-java-agent_20191028_RC00.tar.gz \
  | sudo tar xzv -C /opt/cprof

Die Version des Agents wird während dessen Initialisierung in einem Log gespeichert.

Profiler-Agent laden

Starten Sie zur Profilerstellung für Ihre Anwendungen Java so, wie Sie es normalerweise zum Ausführen Ihres Programms tun, geben Sie jedoch die Optionen für die Agent-Konfiguration an. Zuerst geben Sie den Pfad zur Agent-Bibliothek an. Daraufhin können Sie Optionen an die Bibliothek übergeben.

In der App Engine-Standardumgebung wird der Agent automatisch geladen und konfiguriert. Fahren Sie mit Programm starten fort, um Informationen zum Konfigurieren und Starten Ihres Programms zu erhalten.

Agent-Konfiguration

Zum Konfigurieren des Profiler-Agents fügen Sie das Flag -agentpath hinzu, wenn Sie Ihre Anwendung starten:

 -agentpath:INSTALL_DIR/profiler_java_agent.so=OPTION1,OPTION2,OPTION3

In diesem Ausdruck ist INSTALL_DIR der Pfad zum Profiler-Agent. OPTION1, OPTION2 und OPTION3 hingegen sind Agent-Konfigurationsoptionen. Wenn Sie beispielsweise im vorherigen Ausdruck OPTION1 durch -cprof_service=myapp ersetzen, legen Sie den Dienstnamen auf myapp fest. Für die Anzahl der Optionen und deren Reihenfolge gibt es keine Einschränkungen. In der folgenden Tabelle sind die unterstützten Konfigurationsoptionen aufgeführt:

Agent-Optionen Beschreibung
-cprof_service Wenn Ihre Anwendung nicht in App Engine ausgeführt wird, müssen Sie diese Konfigurationsoption verwenden, um den Dienstnamen festzulegen. Informationen zu Einschränkungen für Dienstnamen finden Sie unter Argumente für Dienstnamen und -versionen.
-cprof_service_version Wenn Sie die Profildaten über die Profiler-Benutzeroberfläche nach der Version des Dienstes analysieren möchten, legen Sie mit dieser Option die Version fest. Informationen zu Versionseinschränkungen finden Sie unter Argumente für Dienstnamen und -versionen.
-cprof_project_id Wenn die Ausführung außerhalb der GCP erfolgt, geben Sie die GCP-Projekt-ID mit dieser Option an. Weitere Informationen finden Sie unter Profilerstellung für Code außerhalb der Google Cloud Platform.
-cprof_zone_name Wenn die Anwendung auf der GCP ausgeführt wird, bestimmt der Profiler-Agent die Zone durch Kommunikation mit dem Compute Engine-Metadatendienst. Wenn der Profiler-Agent nicht mit dem Metadatendienst kommunizieren kann, müssen Sie diese Option verwenden.
-cprof_gce_metadata_server_retry_count
-cprof_gce_metadata_server_retry_sleep_sec
Gemeinsam definieren diese beiden Optionen die Wiederholungsrichtlinie, die der Profiler-Agent bei der Kommunikation mit dem Compute Engine-Metadatendienst verwendet, um Ihre GCP-Projekt-ID und die Informationen zur Zone zu erfassen.

Standardmäßig wird bis zu dreimal ein Neuversuch durchgeführt, mit einer Wartezeit von einer Sekunde zwischen jedem Versuch. Diese Richtlinie ist für die meisten Konfigurationen ausreichend.
-cprof_cpu_use_per_thread_timers Setzen Sie diese Option auf "true", um möglichst genaue CPU-Zeitprofile zu erhalten. Die Verwendung dieser Option führt zu einem erhöhten Overhead pro Thread.

Der Standardwert ist "false".
-cprof_force_debug_non_safepoints Standardmäßig erzwingt der Profiler-Agent von der JVM, dass Debugging-Informationen für JIT-Code (Just-in-Time) und alle Sicherheitspunkte generiert werden. Dies führt zwar zu sehr genauen Funktions- und Standortinformationen auf Zeilenebene für die CPU-Zeit und Heap-Profile, doch entsteht dabei zusätzlicher Agent-Overhead. Wenn Sie das Generieren von Debugging-Informationen für JIT-Code deaktivieren möchten, setzen Sie diese Option auf "false".

Der Standardwert ist "true".
-cprof_wall_num_threads_cutoff Standardmäßig werden Echtzeitprofile nicht erfasst, wenn insgesamt mehr als 4096 Threads in der Anwendung vorliegen. Dieses Limit sorgt dafür, dass die Kosten für den Durchlauf des Thread-Stacks während der Profilerfassung minimal sind. Wenn Ihr Dienst normalerweise mehr als 4096 Threads hat und Sie Profildaten trotz zusätzlichen Overheads erfassen möchten, können Sie das Limit mit diesem Flag erhöhen.

Das Standardlimit beträgt 4096 Threads.
-cprof_enable_heap_sampling Wenn Sie die Heap-Profilerstellung für Java 11 und höher aktivieren möchten, setzen Sie
-cprof_enable_heap_sampling=true. Die Heap-Profilerstellung wird für Java 10 und niedrigere Versionen nicht unterstützt.

Die Heap-Profilerstellung ist standardmäßig deaktiviert.

Wenn Sie die Heap-Profilerstellung aktivieren, ist das Abtastintervall standardmäßig auf 512 KiB eingestellt. Dieses Intervall ist für die meisten Anwendungen ausreichend und verursacht weniger als 0,5 % Overhead für die Anwendung. Abtastintervalle von 256 KiB (262144) bis 1024 KiB (1048576) werden unterstützt. Beispiel: Wenn Sie das Abtastintervall auf 256 KiB festlegen und damit die Abtastrate verdoppeln möchten, fügen Sie folgende Agent-Option hinzu:
-cprof_heap_sampling_interval=262144
Wenn Sie das Abtastintervall auf 1024 KiB festlegen und damit die Abtastrate halbieren möchten, fügen Sie die folgende Agent-Option hinzu:
-cprof_heap_sampling_interval=1048576
Wenn Sie diesen Profiltyp aktivieren, geben Sie beim Bereitstellen der Anwendung eine neue Dienstversion an. Weitere Informationen finden Sie unter Warum habe ich für einen bestimmten Profiltyp keine Daten?

Argumente für Dienstnamen und -versionen

Wenn Sie den Profiler-Agent laden, geben Sie zu dessen Konfiguration ein Argument für den Dienstnamen und ein optionales Argument für die Dienstversion an.

Profiler kann Daten für alle Replikate des unter Dienstname angegebenen Dienstes erfassen. Der Profiler-Dienst hat eine durchschnittliche Erfassungsrate von einem Profil pro Minute für jede Kombination aus Dienstversion und Zone jedes Dienstnamens.

Beispielsweise erstellt Profiler für einen Dienst mit zwei Versionen, dessen Replikate in drei Zonen ausgeführt werden, durchschnittlich sechs Profile pro Minute.

Wenn Sie für die Replikate unterschiedliche Dienstnamen verwenden, werden Dienstprofile häufiger als nötig mit einem entsprechend höheren Overhead erstellt.

Berücksichtigen Sie beim Auswählen eines Dienstnamens Folgendes:

  • Wählen Sie einen Namen aus, der den Dienst in Ihrer Anwendungsarchitektur klar darstellt. Wenn Sie nur einen einzigen Dienst oder eine einzige Anwendung ausführen, spielt der Dienstname eine untergeordnete Rolle. Er gewinnt aber an Bedeutung, wenn Ihre Anwendung beispielsweise in Form mehrerer Mikrodienste ausgeführt wird.

  • Achten Sie darauf, keine prozessspezifischen Werte wie eine Prozess-ID im String für den Dienstnamen zu verwenden.

  • Der String für den Dienstnamen muss diesem regulären Ausdruck entsprechen:

    ^[a-z0-9]([-a-z0-9_.]{0,253}[a-z0-9])?$

Es empfiehlt sich, einen statischen String wie imageproc-service als Dienstnamen zu verwenden.

Die Dienstversion ist optional. Wenn Sie die Dienstversion angeben, kann Profiler Profilinformationen aus mehreren Instanzen aggregieren und korrekt anzeigen. Sie können so verschiedene Versionen Ihrer Dienste kennzeichnen, wenn diese bereitgestellt werden. Die Profiler-Oberfläche ermöglicht Ihnen, die Daten nach Dienstversion zu filtern. So können Sie die Leistung von älteren und neueren Versionen des Codes vergleichen.

Obwohl der Wert des Dienstversionsarguments ein Freitextstring ist, sehen die Werte für dieses Argument meist wie Versionsnummern aus, zum Beispiel 1.0.0 oder 2.1.2.

Programm starten

Compute Engine

Starten Sie Java so, wie Sie es normalerweise zum Ausführen Ihres Programms tun, und fügen Sie die Optionen für die Agent-Konfiguration an:

java \
    -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myapp,-cprof_service_version=1.0.0 \
    JAVA_OPTIONS -jar PATH_TO_YOUR_JAR_FILE PROGRAM_OPTIONS

GKE

Ändern Sie das Dockerfile des Dienstcontainers, um Java so zu starten, wie Sie es normalerweise zum Ausführen Ihres Programms tun, und fügen Sie die Optionen für die Agent-Konfiguration an:

CMD ["java", \
    "-agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myapp,-cprof_service_version=1.0.0", \
     "-jar", "PATH_TO_YOUR_JAR_FILE" ]
    

Flexible Umgebung

Ändern Sie die Konfigurationsdatei app.yaml, um die Umgebungsvariable PROFILER_ENABLE festzulegen. Starten Sie dann Ihr Programm wie gewohnt:

env_variables:
   PROFILER_ENABLE: true

Weitere Informationen finden Sie unter Umgebungsvariablen definieren.

Standardumgebung

Java 21-Laufzeitumgebung

Wenn Sie keine gebündelten Legacy-Dienste verwenden, aktivieren Sie die Profilerfassung, indem Sie die app.yaml-Datei so ändern, dass das Flag agentpath mit einer der folgenden Methoden angegeben wird:

  • Legen Sie die Umgebungsvariable JAVA_TOOL_OPTIONS fest:

    runtime: java21
    env_variables:
      JAVA_TOOL_OPTIONS: "-agentpath:/opt/cprof/profiler_java_agent.so=-logtostderr,-cprof_enable_heap_sampling=true"
    
  • Geben Sie agentpath mit dem Element entrypoint an:

    runtime: java21
    entrypoint: java \
      -agentpath:/opt/cprof/profiler_java_agent.so=-logtostderr,-cprof_enable_heap_sampling=true \
      Main.java
    

Wenn Sie gebündelte Legacy-Dienste verwenden, aktivieren Sie die Profilerfassung, indem Sie die appengine-web.xml-Datei so ändern, dass das Flag agentpath angegeben wird. Verwenden Sie dazu eine der folgenden Methoden:

  • Legen Sie die Umgebungsvariable JAVA_USER_OPTS fest:

    <?xml version="1.0" encoding="utf-8"?>
    <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <env-variables>
    <env-var name="JAVA_USER_OPTS" value="-agentpath:/opt/cprof/profiler_java_agent.so=-logtostderr,-cprof_enable_heap_sampling=true" />
    </env-variables>
    </appengine-web-app>
  • Legen Sie die Umgebungsvariable CPROF_ENABLE fest:

    <?xml version="1.0" encoding="utf-8"?>
    <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <env-variables>
    <env-var name="CPROF_ENABLE" value="-agentpath:/opt/cprof/profiler_java_agent.so=-logtostderr,-cprof_enable_heap_sampling=true" />
    </env-variables>
    </appengine-web-app>
  • Geben Sie agentpath mit dem Element entrypoint an:

    <?xml version="1.0" encoding="utf-8"?>
    <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
      <entrypoint>
       java
       -agentpath:/opt/cprof/profiler_java_agent.so=-logtostderr,-cprof_enable_heap_sampling=true
      </entrypoint>
    </appengine-web-app>

Wenn ein neuer Profiltyp für die Erfassung konfiguriert ist, müssen Sie beim Bereitstellen Ihrer Anwendung eine neue Dienstversion angeben. Weitere Informationen finden Sie unter Warum habe ich für einen bestimmten Profiltyp keine Daten?

Agent-Logging

Der Profiler-Agent kann Logging-Informationen für die flexible App Engine-Umgebung sowie für Compute Engine und GKE erfassen. Der Profiler-Agent unterstützt die folgenden Logging-Ebenen:

  • 0: Alle Meldungen loggen. Standard-Logging-Ebene.
  • 1: Warnungen, Fehler und schwerwiegende Fehler loggen.
  • 2: Fehler und schwerwiegende Fehler loggen.
  • 3: Nur schwerwiegende Fehler loggen und Anwendung beenden.

Wenn Sie das Schreiben von Logs für Standardfehler auf der Standard-Logging-Ebene aktivieren möchten, erweitern Sie die -agentpath-Konfiguration mit -logtostderr.

Wenn Sie die Logging-Ebene so einstellen möchten, dass nur Fehler und schwerwiegende Fehler geloggt werden, erweitern Sie die -agentpath-Konfiguration mit -minloglevel=2.

Wenn Sie beispielsweise das Logging von Fehlern und schwerwiegenden Fehlern zur Standardebene hinzufügen möchten, erweitern Sie die -agentpath-Konfiguration mit -logtostderr und ‑minloglevel=2:

 java -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myapp,-logtostderr,-minloglevel=2 \
   -jar myApp.jar

Fehlerbehebung

In diesem Abschnitt werden Probleme aufgeführt, die speziell bei der Profilerstellung für Java-Anwendungen auftreten. Informationen zu häufig auftretenden Problemen finden Sie unter Fehlerbehebung.

Verhalten Ursache Lösung
Sie haben mehrere Heap-Profiler aktiviert und haben keine Profildaten. Durch die gleichzeitige Verwendung mehrerer Heap-Profiler wird die gesamte Heap-Profilerstellung für Java deaktiviert. Diese Einschränkung erfolgt durch die JVM. 1 Profiler aktivieren

Mit Linux Alpine ausführen

Der Java-Profiler-Agent für Linux Alpine wird nur für Google Kubernetes Engine-Konfigurationen unterstützt.

Informationen zum Installieren des neuesten Java-Profiler-Agents für Linux Alpine finden Sie unter Profiler-Agent installieren.

Authentifizierungsfehler

Wenn Sie Docker-Images wie golang:alpine oder nur alpine verwenden, die mit Linux Alpine ausgeführt werden, wird möglicherweise der folgende Authentifizierungsfehler angezeigt:

connection error: desc = "transport: authentication handshake failed: x509: failed to load system roots and no roots provided"

Der Fehler ist nur sichtbar, wenn Agent-Logging aktiviert ist.

Der Fehler zeigt an, dass die Root-SSL-Zertifikate für die Docker-Images mit Linux Alpine nicht standardmäßig installiert sind. Diese Zertifikate sind erforderlich, damit der Profiler-Agent mit der Profiler API kommunizieren kann. Fügen Sie Ihrem Dockerfile den folgenden apk-Befehl hinzu, um diesen Fehler zu beheben:

FROM alpine
...
RUN apk add --no-cache ca-certificates

Sie müssen dann Ihre Anwendung neu erstellen und noch einmal bereitstellen.

Nächste Schritte