Crea perfiles de aplicaciones de Java

En esta página, se describe cómo modificar tu aplicación de Java para capturar datos de creación de perfiles y enviarlos a tu proyecto de Google Cloud. Para obtener información general sobre la creación de perfiles, consulta el artículo sobre conceptos de creación de perfiles.

Tipos de perfiles para Java:

  • Tiempo de CPU
  • Montón (requiere Java 11 o entorno estándar de App Engine, inhabilitado de forma predeterminada)
  • Tiempo (no disponible para el entorno estándar de App Engine en Java 8)

Versiones del lenguaje Java compatibles:

  • JVMs basadas en hotspot (incluidos Oracle JDK y algunas compilaciones de OpenJDK) para Java 8, 11 y versiones posteriores

Versiones compatibles del agente de generación de perfiles:

  • Se admite la versión más reciente del agente. Por lo general, no se admiten las actualizaciones de más de un año. Te recomendamos usar la versión más reciente del agente.

Sistemas operativos compatibles:

  • Linux. La creación de perfiles de aplicaciones de Java es compatible con kernels de Linux cuya biblioteca C estándar se implementa con glibc o musl. Para obtener información de configuración específica de los kernels Linux Alpine, consulta la sección sobre ejecución en Linux Alpine.

Entornos compatibles:

Habilita la API de Profiler

Antes de usar el agente de generación de perfiles, asegúrate de que la API de Profiler subyacente esté habilitada. Puedes verificar el estado de la API y habilitarla, si es necesario, con Google Cloud CLI o la consola de Google:

gcloud CLI

  1. Si aún no instalaste Google Cloud CLI en tu estación de trabajo, consulta la documentación de Google Cloud CLI.

  2. Ejecuta el siguiente comando:

    gcloud services enable cloudprofiler.googleapis.com
    

Para obtener más información, consulta gcloud services

Consola de Google Cloud

  1. En el panel de navegación de la consola de Google Cloud, selecciona API y servicios, haz clic en Habilitar API y servicios y, luego, habilita la API de Cloud Profiler:

    Ir a la configuración de la API de Profiler

  2. Si aparece API habilitada, la API ya está habilitada. De lo contrario, haz clic en el botón Habilitar.

Instala el agente de Profiler

Compute Engine

  1. Crea un directorio de instalación, por ejemplo, /opt/cprof, para el agente de Profiler:

     sudo mkdir -p /opt/cprof

  2. Descarga el archivo del agente del repositorio storage.googleapis.com y extráelo en el directorio de instalación:

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

GKE

Modifica el Dockerfile a fin de crear un directorio de instalación para el agente de Profiler, descarga el archivo del agente y, luego, extráelo en el directorio de instalación.

Linux (biblioteca C basada en glibc):

Usa el siguiente comando de instalación:

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 (biblioteca C basada en musl):

Usa el siguiente comando de instalación:

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

Entorno flexible

Cuando usas la imagen base del entorno de ejecución de Java 8 de Google o del entorno de ejecución de Java 9 o Jetty 9, el agente de Profiler está preinstalado, por lo que no deberás realizar pasos adicionales para instalarlo.

Para todas las demás imágenes base, debes instalar el agente. Por ejemplo, el siguiente Dockerfile contiene las instrucciones para usar la imagen openjdk:11-slim e instalar el agente de Profiler. Además, define los parámetros predeterminados que se usarán cuando se inicie la aplicación:

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

Para usar este Dockerfile con el entorno flexible de App Engine, debes hacer lo siguiente:

  • Reemplaza OPTION1 y OPTION2 por los valores de configuración del agente necesarios para tu aplicación, y PATH_TO_YOUR_JAR_FILE por la ruta de acceso a tu archivo .jar.
  • Coloca Dockerfile en el mismo directorio que tu archivo app.yaml.
  • Modifica tu archivo app.yaml para especificar un entorno de ejecución personalizado. Para obtener más información, consulta Compila entornos de ejecución personalizados.

Entorno estándar

Cuando usas el entorno de ejecución de Java, el agente de Profiler está preinstalado, por lo que no es necesario realizar pasos adicionales para instalarlo. Para Java 11 y versiones posteriores, está preinstalado en /opt/cprof.

Fuera de Google Cloud

  1. Crea un directorio de instalación, por ejemplo, /opt/cprof, para el agente de Profiler:

     sudo mkdir -p /opt/cprof

  2. Descarga el archivo del agente del repositorio storage.googleapis.com y extráelo en el directorio de instalación:

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

A fin de enumerar todas las versiones del agente disponibles para la descarga, ejecuta el siguiente comando:

gsutil ls gs://cloud-profiler/java/cloud-profiler-*

La respuesta del comando es similar a la siguiente:

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

Para descargar una versión específica del agente, pasa su URL al comando de descarga. Por ejemplo, para descargar el agente compilado el 28 de octubre de 2019, usarías la siguiente declaración:

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 versión del agente se registra durante su inicialización.

Carga el agente de Profiler

A fin de crear perfiles de tu aplicación, inicia Java como lo harías normalmente para ejecutar tu programa, pero especifica las opciones de configuración del agente. Una vez que especifiques la ruta de acceso a la biblioteca del agente podrás pasar opciones a la biblioteca.

Para el entorno estándar de App Engine, el agente se carga y configura automáticamente. Ve a la sección cómo iniciar tu programa para obtener detalles sobre cómo configurar e iniciar tu programa.

Configuración del agente

Para configurar el agente de creación de perfiles, incluye la marca -agentpath cuando inicias tu aplicación:

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

En esta expresión, INSTALL_DIR es la ruta de acceso al agente de creación de perfiles, mientras que OPTION1, OPTION2 y OPTION3 son opciones de configuración del agente. Por ejemplo, si reemplazas OPTION1 por -cprof_service=myapp en la expresión anterior, estableces el nombre del servicio en myapp. No hay restricciones en la cantidad de opciones ni en su orden. Las opciones de configuración compatibles se enumeran en la siguiente tabla:

Opción de agente Descripción
-cprof_service Si tu aplicación no se ejecuta en App Engine, debes usar esta opción de configuración para establecer el nombre del servicio. Para conocer las restricciones del nombre del servicio, consulta la sección sobre argumentos de la versión y del nombre del servicio.
-cprof_service_version Cuando quieras analizar los datos de creación de perfiles con la IU de Profiler según la versión del servicio, usa esta opción para establecer la versión. Para conocer las restricciones de la versión, consulta la sección sobre argumentos de la versión y del nombre del servicio.
-cprof_project_id Cuando realices la ejecución fuera de Google Cloud, usa esta opción para especificar tu ID del proyecto de Google Cloud. Para obtener más información, consulta la sección sobre cómo crear perfiles de aplicaciones que se ejecutan fuera de Google Cloud.
-cprof_zone_name Cuando tu aplicación se ejecuta en Google Cloud, el agente de creación de perfiles determina la zona mediante la comunicación con el servicio de metadatos de Compute Engine. Si el agente de creación de perfiles no puede comunicarse con el servicio de metadatos, debes usar esta opción.
-cprof_gce_metadata_server_retry_count
-cprof_gce_metadata_server_retry_sleep_sec
En conjunto, estas dos opciones definen la política de reintento que usa el agente de Profiler cuando se comunica con el servicio de metadatos de Compute Engine para recopilar información del ID y la zona del proyecto de Google Cloud.

La política predeterminada es reintentar 3 veces y esperar 1 segundo entre cada intento. Esta política es suficiente para la mayoría de las configuraciones.
-cprof_cpu_use_per_thread_timers Para obtener los perfiles de tiempo de CPU más precisos, configura esta opción como verdadera. El uso de esta opción genera una sobrecarga por subproceso.

El valor predeterminado es falso.
-cprof_force_debug_non_safepoints De forma predeterminada, el agente de creación de perfiles hace que la JVM genere información de depuración para todo el código generado just-in-time (JIT), además de generar información de depuración para todos los puntos de seguridad. Esto da como resultado la información más precisa sobre la función y la ubicación a nivel de línea para el tiempo de CPU y los perfiles del montón a expensas de la sobrecarga del agente adicional. Puedes inhabilitar la generación de información de depuración para el código JIT si configuras esta opción como falsa.

El valor predeterminado es verdadero.
-cprof_wall_num_threads_cutoff De forma predeterminada, los perfiles de tiempo no se recopilan si la cantidad total de subprocesos en la aplicación supera los 4096. El límite garantiza que, durante la recopilación del perfil, el costo de recorrer la pila de subprocesos sea mínimo. Si tu servicio normalmente tiene más de 4096 subprocesos y deseas recopilar datos de creación de perfiles a expensas de una sobrecarga adicional, usa esta marca para aumentar el límite.

El límite predeterminado es de 4096 subprocesos.
-cprof_enable_heap_sampling A fin de habilitar la creación de perfiles del montón para Java 11 y versiones posteriores, configura
-cprof_enable_heap_sampling=true. La creación de perfiles del montón no es compatible con Java 10 y versiones anteriores.

La creación de perfiles del montón está inhabilitada de forma predeterminada.

Cuando habilitas la creación de perfiles del montón, el intervalo de muestreo se establece en 512 KiB de forma predeterminada. Este intervalo es suficiente para la mayoría de las aplicaciones y genera menos del 0.5% de sobrecarga para la aplicación. Se admiten intervalos de muestreo de 256 KiB (262144) a 1024 KiB (1048576). Por ejemplo, para establecer el intervalo de muestreo en 256 KiB, que duplica la tasa de muestreo, agrega la opción de agente:

-cprof_heap_sampling_interval=262144
De manera similar, para establecer el intervalo de muestreo en 1,024 KiB, que reduce a la mitad la tasa de muestreo, agrega la opción de agente:

-cprof_heap_sampling_interval=1048576
Si habilitas este tipo de perfil, especifica una versión de servicio nueva cuando implementes tu aplicación. Para obtener más información, consulta la sección ¿Por qué no tengo datos para un tipo de perfil específico?

Argumentos de la versión y del nombre del servicio

Cuando cargas el agente de Profiler, especificas un argumento de nombre del servicio y un argumento de la versión del servicio opcional para configurarlo.

El nombre del servicio permite que Profiler recopile datos de generación de perfiles para todas las réplicas de ese servicio. El servicio del generador de perfiles garantiza una tasa promedio de recopilación de un perfil por minuto para cada nombre de servicio en cada combinación de zonas y versiones del servicio.

Por ejemplo, si tienes un servicio con dos versiones que se ejecutan en réplicas en tres zonas, el generador de perfiles creará un promedio de 6 perfiles por minuto para ese servicio.

Si usas nombres de servicio diferentes para tus réplicas, se generarán los perfiles del servicio con más frecuencia que la necesaria y con una sobrecarga más alta.

Cuando selecciones un nombre de servicio, ten en cuenta lo siguiente:

  • Elige un nombre que represente de forma clara el servicio en la arquitectura de tu aplicación. La elección del nombre del servicio es menos importante si solo ejecutas un único servicio o aplicación. Por ejemplo, es más importante si tu aplicación se ejecuta como un conjunto de microservicios.

  • Asegúrate de no usar ningún valor específico del proceso, como un ID de proceso, en la string de nombre del servicio.

  • La string de nombre del servicio debe coincidir con esta expresión regular:

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

Un buen lineamiento es usar una string estática, como imageproc-service, como nombre del servicio.

La versión del servicio es opcional. Si especificas la versión del servicio, Profiler puede agregar información de generación de perfiles de varias instancias y mostrarla correctamente. Se puede usar para marcar diferentes versiones de tus servicios a medida que se implementan. La IU de Profiler te permite filtrar los datos por versión del servicio. De esta manera, puedes comparar el rendimiento de las versiones anteriores y más recientes del código.

El valor del argumento de la versión del servicio es una string de formato libre, pero los valores para este argumento suelen verse como números de versión, por ejemplo, 1.0.0 o 2.1.2.

Inicia tu programa

Compute Engine

Inicia Java como lo harías normalmente para ejecutar tu programa y agrega las opciones de configuración del 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 el Dockerfile del contenedor del servicio para iniciar Java como lo harías normalmente a fin de ejecutar tu programa y agrega las opciones de configuración del 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" ]
    

Entorno flexible

Modifica el archivo de configuración app.yaml para establecer la variable de entorno PROFILER_ENABLE. Luego, inicia el programa como de costumbre:

env_variables:
   PROFILER_ENABLE: true

Consulta la sección sobre cómo definir variables de entorno para obtener más información.

Entorno estándar

Entorno de ejecución de Java 21

Si no usas servicios agrupados en paquetes heredados, habilita la colección del generador de perfiles. Para ello, modifica el archivo app.yaml a fin de especificar la marca agentpath con cualquiera de los siguientes métodos:

  • Configura la variable de entorno JAVA_TOOL_OPTIONS:

    runtime: java21
    env_variables:
      JAVA_TOOL_OPTIONS: "-agentpath:/opt/cprof/profiler_java_agent.so=-logtostderr,-cprof_enable_heap_sampling=true"
    
  • Especifica el agentpath con el elemento entrypoint:

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

Si usas servicios agrupados en paquetes heredados, habilita la colección del generador de perfiles. Para ello, modifica el archivo appengine-web.xml a fin de especificar la marca agentpath con cualquiera de los siguientes métodos:

  • Configura la variable de entorno 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>
    
  • Configura la variable de entorno 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>
    
  • Especifica el agentpath con el 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>
    

Si se configura un nuevo tipo de perfil para la recopilación, asegúrate de especificar una nueva versión del servicio cuando implementas tu aplicación. Para obtener más información, consulta ¿Por qué no tengo datos para un tipo de perfil específico?

Registro de agente

El agente de creación de perfiles puede reportar información de registro para el entorno flexible de App Engine, Compute Engine y GKE. El agente de creación de perfiles admite los siguientes niveles de registro:

  • 0: registra todos los mensajes. Nivel de registro predeterminado.
  • 1: registra advertencias, errores y mensajes graves.
  • 2: registra errores y mensajes graves.
  • 3: registra solo los mensajes graves y detiene la aplicación.

Para habilitar la escritura de registros en el error estándar con el nivel de registro predeterminado, agrega -logtostderr a la configuración -agentpath.

Para configurar el nivel de registro de modo que solo se registren errores y mensajes graves, agrega -minloglevel=2 a la configuración -agentpath.

Por ejemplo, para habilitar el registro de mensajes de error y no recuperables en el error estándar, agrega -logtostderr y ‑minloglevel=2 a la configuración de -agentpath:

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

Soluciona problemas

En esta sección se enumeran los problemas específicos de la creación de perfiles de aplicaciones de Java. Consulta la página Solución de problemas a fin de obtener ayuda para resolver problemas comunes.

Comportamiento Causa Solución
Habilitaste varios generadores de perfiles del montón y no tienes datos de perfil. El uso simultáneo de varios generadores de perfiles del montón inhabilita la compatibilidad con la creación de perfiles del montón para Java. Esta es una limitación de la JVM. Habilita 1 generador de perfiles.

Ejecuta con Linux Alpine

El agente de creación de perfiles de Java para Linux Alpine solo es compatible con las configuraciones de Google Kubernetes Engine.

Si deseas instalar el agente de creación de perfiles de Java más reciente para Linux Alpine, consulta Instala el agente de Profiler.

Error de autenticación

Si usas imágenes de Docker que se ejecutan con Linux Alpine (como golang:alpine o solo alpine), es posible que veas el siguiente error de autenticación:

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

Ten en cuenta que, para ver el error, debes tener habilitado el registro de agente.

El error indica que las imágenes de Docker con Linux Alpine no tienen los certificados SSL raíz instalados de forma predeterminada. Esos certificados son necesarios para que el agente de creación de perfiles se comunique con la API de Profiler. Para resolver este error, agrega el siguiente comando apk a tu Dockerfile:

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

Luego, debes volver a compilar y volver a implementar tu aplicación.

¿Qué sigue?