Profilazione delle applicazioni Java

Questa pagina descrive come modificare l'applicazione Java per acquisire i dati di profilazione e inviarli al tuo progetto Google Cloud. Per informazioni generali sulla profilazione, vedi Concetti di profilazione.

Tipi di profilo per Java:

  • Tempo CPU
  • Heap (richiede Java 11 o l'ambiente standard di App Engine, disattivato per impostazione predefinita)
  • Tempo reale (non disponibile per l'ambiente standard di App Engine Java 8)

Versioni del linguaggio Java supportate:

  • JVM basate su HotSpot (inclusi Oracle JDK e alcune build OpenJDK) per Java 8, 11 o versioni successive.

Versioni dell'agente di profilazione supportate:

  • È supportata la versione più recente dell'agente. In generale, le release più vecchie di un anno non sono supportate. Ti consigliamo di utilizzare la versione dell'agente rilasciata più di recente.

Sistemi operativi supportati:

  • Linux. La profilazione delle applicazioni Java è supportata per i kernel Linux la cui libreria C standard è implementata con glibc o con musl. Per informazioni di configurazione specifiche per i kernel Linux Alpine, vedi Esecuzione su Linux Alpine.

Ambienti supportati:

Attivazione dell'API Profiler

Prima di utilizzare l'agente di profilazione, assicurati che l'API Profiler sottostante sia abilitata. Puoi controllare lo stato dell'API e abilitarla, se necessario, utilizzando Google Cloud CLI o la console Google Cloud :

Interfaccia a riga di comando gcloud

  1. Se non hai ancora installato Google Cloud CLI sulla tua workstation, consulta la documentazione di Google Cloud CLI.

  2. Esegui questo comando:

    gcloud services enable cloudprofiler.googleapis.com
    

Per ulteriori informazioni, vedi gcloud services.

Console Google Cloud

  1. Enable the required API.

    Enable the API

  2. Se viene visualizzato il messaggio API abilitata, l'API è già abilitata. In caso contrario, fai clic sul pulsante Attiva.

Concedi ruolo IAM al account di servizio

Se stai eseguendo il deployment dell'applicazione sulle risorse Google Cloud e se utilizzi il account di servizio predefinito e non hai modificato le concessioni di ruolo a questo account di servizio, puoi saltare questa sezione.

Se esegui una delle seguenti operazioni, devi concedere all'account di servizio il ruolo IAM Agente Cloud Profiler (roles/cloudprofiler.agent):

  1. Stai utilizzando il account di servizio predefinito, ma hai modificato le concessioni di ruolo.
  2. Stai utilizzando un account di servizio creato dall'utente.
  3. Stai utilizzando Workload Identity, concedi il ruolo Agente Cloud Profiler al account di servizio Kubernetes.

Puoi concedere un ruolo IAM a un account di servizio utilizzando la consoleGoogle Cloud o Google Cloud CLI. Ad esempio, potresti utilizzare il comando gcloud projects add-iam-policy-binding:

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

Prima di utilizzare il comando precedente, sostituisci quanto segue:

  • GCP_PROJECT_ID: il tuo ID progetto.
  • MY_SVC_ACCT_ID: il nome del account di servizio.

Per informazioni dettagliate, vedi Gestire l'accesso a progetti, cartelle e organizzazioni.

Installazione dell'agente Profiler

Compute Engine

  1. Crea una directory di installazione, ad esempio /opt/cprof, per l'agente Profiler:

     sudo mkdir -p /opt/cprof

  2. Scarica l'archivio dell'agente dal repository storage.googleapis.com ed estrailo nella directory di installazione:

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

GKE

Modifica Dockerfile per creare una directory di installazione per l'agente Profiler, scarica l'archivio dell'agente, quindi estrailo nella directory di installazione.

Linux (libreria C basata su glibc):

Utilizza il seguente comando di installazione:

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 (libreria C basata su musl):

Utilizza il seguente comando di installazione:

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

Ambiente flessibile

Quando utilizzi l'immagine di base del runtime Java 8 di Google o l'immagine di base del runtime Java 9 / Jetty 9, l'agente Profiler è preinstallato, quindi non devi eseguire ulteriori passaggi per installarlo.

Per tutte le altre immagini di base, devi installare l'agente. Ad esempio, il seguente Dockerfile contiene le istruzioni per utilizzare l'immagine openjdk:11-slim, installare l'agente Profiler e definisce i parametri predefiniti da utilizzare all'avvio dell'applicazione:

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"]

Per utilizzare questo Dockerfile con l'ambiente flessibile di App Engine, devi fare quanto segue:

  • Sostituisci OPTION1 e OPTION2 con i valori della configurazione dell'agente necessari per la tua applicazione e sostituisci PATH_TO_YOUR_JAR_FILE con il percorso del file JAR.
  • Inserisci Dockerfile nella stessa directory del file app.yaml.
  • Modifica il file app.yaml per specificare un runtime personalizzato. Per ulteriori informazioni, vedi Creazione di runtime personalizzati.

Ambiente standard

Quando utilizzi l'ambiente di runtime Java, l'agente Profiler è preinstallato, quindi non devi eseguire ulteriori passaggi per installarlo. Per Java versione 11 e successive, è preinstallato in /opt/cprof.

Al di fuori di Google Cloud

  1. Crea una directory di installazione, ad esempio /opt/cprof, per l'agente Profiler:

     sudo mkdir -p /opt/cprof

  2. Scarica l'archivio dell'agente dal repository storage.googleapis.com ed estrailo nella directory di installazione:

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

Per elencare tutte le versioni dell'agente disponibili per il download, esegui questo comando:

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

La risposta del comando è simile alla seguente:

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

Per scaricare una versione specifica dell'agente, passa il relativo URL al comando di download. Ad esempio, per scaricare l'agente creato il 28 ottobre 2019, utilizzeresti la seguente istruzione:

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

La versione dell'agente viene registrata durante l'inizializzazione.

Caricamento dell'agente Profiler

Per profilare l'applicazione, avvia Java come faresti normalmente per eseguire il programma, ma specifica le opzioni di configurazione dell'agente. Specifica il percorso della libreria dell'agente e puoi passare le opzioni alla libreria.

Per l'ambiente standard di App Engine, l'agente viene caricato e configurato automaticamente. Vai direttamente alla sezione Avvio del programma per informazioni dettagliate sulla configurazione e l'avvio del programma.

Configurazione dell'agente

Per configurare l'agente di profilazione, includi il flag -agentpath all'avvio dell'applicazione:

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

In questa espressione, INSTALL_DIR è il percorso dell'agente di profilazione, mentre OPTION1, OPTION2 e OPTION3 sono opzioni di configurazione dell'agente. Ad esempio, se sostituisci OPTION1 con -cprof_service=myapp nell'espressione precedente, imposti il nome del servizio su myapp. Non esistono limitazioni al numero di opzioni o al loro ordine. Le opzioni di configurazione supportate sono elencate nella tabella seguente:

Opzione agente Descrizione
-cprof_service Se la tua applicazione non è in esecuzione su App Engine, devi utilizzare questa opzione di configurazione per impostare il nome del servizio. Per le limitazioni relative al nome del servizio, vedi Argomenti del nome e della versione del servizio.
-cprof_service_version Se vuoi analizzare i dati di profilazione utilizzando l'interfaccia utente di Profiler in base alla versione del servizio, utilizza questa opzione per impostare la versione. Per le limitazioni di versione, vedi Argomenti del nome e della versione del servizio.
-cprof_project_id Quando esegui l'operazione al di fuori di Google Cloud, utilizza questa opzione per specificare l' Google Cloud ID progetto. Per maggiori informazioni, vedi Profilazione delle applicazioni in esecuzione al di fuori di Google Cloud.
-cprof_zone_name Quando l'applicazione è in esecuzione su Google Cloud, l'agente di profilazione determina la zona comunicando con il servizio di metadati di Compute Engine. Se l'agente di profilazione non riesce a comunicare con il servizio di metadati, devi utilizzare questa opzione.
-cprof_gce_metadata_server_retry_count
-cprof_gce_metadata_server_retry_sleep_sec
Insieme, queste due opzioni definiscono il criterio di ripetizione utilizzato dall'agente profiler quando comunica con il servizio di metadati di Compute Engine. per raccogliere l'ID progetto e le informazioni sulla zona. Google Cloud

La policy predefinita prevede fino a 3 tentativi con un'attesa di 1 secondo tra un tentativo e l'altro. Questo criterio è sufficiente per la maggior parte delle configurazioni.
-cprof_cpu_use_per_thread_timers Per ottenere profili del tempo CPU più accurati, imposta questa opzione su true. L'utilizzo di questa opzione comporta un aumento dell'overhead per thread.

Il valore predefinito è false.
-cprof_force_debug_non_safepoints Per impostazione predefinita, l'agente di profilazione forza la JVM a generare informazioni di debug per tutto il codice generato JIT (just in time), oltre a generare informazioni di debug per tutti i safepoint. In questo modo si ottengono le informazioni più accurate a livello di funzione e riga per il tempo CPU e i profili heap a scapito di un overhead aggiuntivo dell'agente. Puoi disattivare la generazione di informazioni di debug per il codice JIT impostando questa opzione su false.

Il valore predefinito è true.
-cprof_wall_num_threads_cutoff Per impostazione predefinita, i profili del thread non vengono raccolti se il numero totale di thread nell'applicazione supera 4096. Il limite garantisce che durante la raccolta dei profili, il costo di attraversamento dello stack di thread sia minimo. Se il tuo servizio normalmente ha più di 4096 thread e vuoi raccogliere dati di profilazione a scapito di un overhead aggiuntivo, utilizza questo flag per aumentare il limite.

Il limite predefinito è 4096 thread.
-cprof_enable_heap_sampling Per attivare la profilazione dell'heap per Java 11 e versioni successive, imposta
-cprof_enable_heap_sampling=true. La profilazione dell'heap non è supportata per Java 10 e versioni precedenti.

La profilazione dell'heap è disattivata per impostazione predefinita.

Quando attivi la profilazione dell'heap, l'intervallo di campionamento è impostato su 512 KiB per impostazione predefinita. Questo intervallo è sufficiente per la maggior parte delle applicazioni e comporta un overhead inferiore allo 0,5% per l'applicazione. Sono supportati intervalli di campionamento da 256 KiB (262144) a 1024 KiB (1048576). Ad esempio, per impostare l'intervallo di campionamento su 256 KiB, il che raddoppia la frequenza di campionamento, aggiungi l'opzione dell'agente:
-cprof_heap_sampling_interval=262144
Allo stesso modo, per impostare l'intervallo di campionamento su 1024 KiB, che dimezza la frequenza di campionamento, aggiungi l'opzione dell'agente:
-cprof_heap_sampling_interval=1048576
Se abiliti questo tipo di profilo, specifica una nuova versione del servizio quando esegui il deployment dell'applicazione. Per ulteriori informazioni, vedi Perché non ho dati per un tipo di profilo specifico?

Argomenti del nome e della versione del servizio

Quando carichi l'agente Profiler, specifichi un argomento service-name e un argomento service-version facoltativo per configurarlo.

Il nome del servizio consente a Profiler di raccogliere dati di profilazione per tutte le repliche del servizio. Il servizio di profilazione garantisce una velocità di raccolta di un profilo al minuto, in media, per ogni nome di servizio in ogni combinazione di versioni e zone del servizio.

Ad esempio, se hai un servizio con due versioni in esecuzione su repliche in tre zone, il profiler creerà una media di 6 profili al minuto per quel servizio.

Se utilizzi nomi di servizio diversi per le repliche, il servizio verrà profilato più spesso del necessario, con un overhead corrispondentemente più elevato.

Quando selezioni un nome servizio:

  • Scegli un nome che rappresenti chiaramente il servizio nell'architettura dell'applicazione. La scelta del nome del servizio è meno importante se esegui un solo servizio o applicazione. È più importante se la tua applicazione viene eseguita come un insieme di microservizi, ad esempio.

  • Assicurati di non utilizzare valori specifici del processo, come un ID processo, nella stringa service-name.

  • La stringa service-name deve corrispondere a questa espressione regolare:

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

Una buona linea guida è utilizzare una stringa statica come imageproc-service come nome del servizio.

La versione del servizio è facoltativa. Se specifichi la versione del servizio, Profiler può aggregare le informazioni di profilazione da più istanze e visualizzarle correttamente. Può essere utilizzato per contrassegnare le diverse versioni dei tuoi servizi durante la loro implementazione. L'interfaccia utente di Profiler ti consente di filtrare i dati in base alla versione del servizio, in modo da confrontare il rendimento delle versioni precedenti e più recenti del codice.

Il valore dell'argomento service-version è una stringa in formato libero, ma i valori per questo argomento in genere assomigliano a numeri di versione, ad esempio, 1.0.0 o 2.1.2.

Iniziare il programma

Compute Engine

Avvia Java come faresti normalmente per eseguire il programma e aggiungi le opzioni di configurazione dell'agente:

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

Modifica il Dockerfile del contenitore di servizio per avviare Java come faresti normalmente per eseguire il programma e aggiungi le opzioni di configurazione dell'agente:

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

Ambiente flessibile

Modifica il file di configurazione app.yaml per impostare la variabile di ambiente PROFILER_ENABLE. Poi inizia il programma come al solito:

env_variables:
   PROFILER_ENABLE: true

Per saperne di più, consulta Definizione delle variabili di ambiente.

Ambiente standard

Java 21 runtime environment

Se non utilizzi i servizi in bundle legacy, attiva la raccolta del profiler modificando il file app.yaml per specificare il flag agentpath utilizzando uno dei seguenti metodi:

  • Imposta la variabile di ambiente JAVA_TOOL_OPTIONS:

    runtime: java21
    env_variables:
      JAVA_TOOL_OPTIONS: "-agentpath:/opt/cprof/profiler_java_agent.so=-logtostderr,-cprof_enable_heap_sampling=true"
    
  • Specifica agentpath utilizzando l'elemento entrypoint:

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

Se utilizzi servizi in bundle legacy, attiva la raccolta del profiler modificando il file appengine-web.xml per specificare il flag agentpath utilizzando uno dei seguenti metodi:

  • Imposta la variabile di ambiente JAVA_USER_OPTS:

    <?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>
  • Imposta la variabile di ambiente CPROF_ENABLE:

    <?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>
  • Specifica agentpath utilizzando l'elemento entrypoint:

    <?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>

Se è configurato un nuovo tipo di profilo per la raccolta, assicurati di specificare una nuova versione del servizio quando esegui il deployment dell'applicazione. Per maggiori informazioni, vedi Perché non ho dati per un tipo di profilo specifico?

Logging dell'agente

L'agente di profilazione può segnalare informazioni di logging per l'ambiente flessibile App Engine, Compute Engine e GKE. L'agente di profilazione supporta i seguenti livelli di logging:

  • 0: registra tutti i messaggi. Livello di registrazione predefinito.
  • 1: registra avvisi, errori e messaggi irreversibili.
  • 2: registra gli errori e i messaggi irreversibili.
  • 3: registra solo i messaggi irreversibili e arresta l'applicazione.

Per attivare la scrittura dei log nell'errore standard con il livello di logging predefinito, aggiungi -logtostderr alla configurazione -agentpath.

Per impostare il livello di logging in modo da registrare solo i messaggi di errore e irreversibili, aggiungi -minloglevel=2 alla configurazione di -agentpath.

Ad esempio, per attivare la registrazione dei messaggi di errore e irreversibili nell'errore standard, aggiungi -logtostderr e ‑minloglevel=2 alla configurazione -agentpath:

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

Risoluzione dei problemi

Questa sezione elenca i problemi specifici della profilazione delle applicazioni Java. Per assistenza per problemi comuni, consulta la sezione Risoluzione dei problemi.

Comportamento Causa Soluzione
Hai attivato più profiler dell'heap e non hai dati del profilo. L'utilizzo simultaneo di più profiler heap disabilita tutto il supporto per la profilazione heap per Java. Si tratta di una limitazione della JVM. Attiva un profiler.

Esecuzione con Linux Alpine

L'agente di profilazione Java per Linux Alpine è supportato solo per le configurazioni Google Kubernetes Engine.

Per installare l'agente di profilazione Java più recente per Linux Alpine, consulta Installazione dell'agente Profiler.

Errore di autenticazione

Se utilizzi immagini Docker eseguite con Linux Alpine (ad esempio golang:alpine o semplicemente alpine), potresti visualizzare il seguente errore di autenticazione:

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

Tieni presente che per visualizzare l'errore devi aver attivato la registrazione dell'agente.

L'errore indica che le immagini Docker con Linux Alpine non hanno i certificati SSL root installati per impostazione predefinita. Questi certificati sono necessari perché l'agente di profilazione comunichi con l'API Profiler. Per risolvere questo errore, aggiungi il seguente comando apk al Dockerfile:

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

Dopodiché, devi ricompilare e ridistribuire l'applicazione.

Passaggi successivi