Como criar perfis de aplicativos Java

Esta página explica como modificar seu aplicativo Java para capturar dados de criação de perfil e enviá-los para seu projeto do Google Cloud. Para informações gerais sobre criação de perfil, consulte Conceitos de criação de perfil.

Tipos de perfil para Java:

  • Tempo de CPU
  • Heap (requer Java 11 ou ambiente padrão do App Engine, desativado por padrão)
  • Tempo decorrido (não disponível para o Java 8 no ambiente padrão do App Engine)

Versões compatíveis com a linguagem Java:

  • JVMs baseadas em HotSpot (incluindo Oracle JDK e alguns builds do OpenJDK) para Java 8, 11 ou posterior.

Versões compatíveis com o agente de criação de perfil:

  • A versão mais recente do agente é compatível. Em geral, lançamentos com mais de um ano não são compatíveis. Recomendamos que você use a versão do agente lançada mais recentemente.

Sistemas operacionais compatíveis:

  • Linux. A criação de perfil de aplicativos Java é compatível com kernels do Linux em que a biblioteca C padrão foi implementada com glibc ou musl. Saiba mais sobre informações de configuração específicas aos kernels do Alpine Linux em Como executar no Alpine Linux.

Ambientes compatíveis:

Como ativar a API Profiler

Antes de usar o agente de criação de perfil, garanta que a API Profiler subjacente esteja ativada. É possível verificar o status da API e ativá-la, se necessário, usando a CLI do Google Cloud ou o Console do Google Cloud:

CLI gcloud

  1. Se você ainda não instalou a CLI do Google Cloud na sua estação de trabalho, consulte a documentação da CLI do Google Cloud.

  2. Execute este comando:

    gcloud services enable cloudprofiler.googleapis.com
    

Para ver mais informações, consulte gcloud services.

Console do Google Cloud

  1. Enable the required API.

    Enable the API

  2. Se a mensagem API ativada for exibida, quer dizer que a API já está ativada. Caso contrário, clique no botão Ativar.

Conceder papel do IAM à conta de serviço

Se você estiver implantando seu aplicativo em recursos do Google Cloud e se você estiver usando a conta de serviço padrão e não tiver modificado as permissões de função para essa conta de serviço, pule esta seção.

Se você fizer qualquer uma das ações a seguir, precisará conceder à conta de serviço o papel do IAM de Agente do Cloud Profiler (roles/cloudprofiler.agent):

  1. Você está usando a conta de serviço padrão, mas modificou as permissões de função dela.
  2. Você está usando uma conta de serviço criada pelo usuário.
  3. Você está usando a Identidade da carga de trabalho, conceda o papel de agente do Cloud Profiler à conta de serviço do Kubernetes.

É possível conceder um papel do IAM a uma conta de serviço usando o console do Google Cloud ou a Google Cloud CLI. Por exemplo, é possível usar o 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

Antes de usar o comando anterior, substitua o seguinte:

  • GCP_PROJECT_ID: o ID do projeto.
  • MY_SVC_ACCT_ID: o nome da conta de serviço

Para mais informações, consulte Gerenciar o acesso a projetos, pastas e organizações.

Como instalar o agente do Profiler

Compute Engine

  1. Crie um diretório de instalação, por exemplo, /opt/cprof, para o agente do Profiler:

     sudo mkdir -p /opt/cprof

  2. Faça o download do arquivo do agente no repositório storage.googleapis.com e extraia-o no diretório de instalação:

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

GKE

Modifique o Dockerfile para criar um diretório de instalação para o agente do Profiler, faça o download do arquivo do agente e o extraia no diretório de instalação.

Linux (biblioteca C baseada em glibc):

Use o seguinte comando de instalação:

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

Alpine Linux (biblioteca C baseada em musl):

Use o seguinte comando de instalação:

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

Ambiente flexível

Quando você usa a imagem de base do ambiente de execução do Java 8 do Google ou a imagem de base do ambiente de execução Java 9 / Jetty 9, o agente do Profiler está pré-instalado. Portanto, não há mais etapas necessárias para instalá-lo.

Para todas as outras imagens de base, é preciso instalar o agente. Por exemplo, o Dockerfile a seguir contém as instruções para usar a imagem openjdk:11-slim e instalar o agente do Profiler, além de definir os parâmetros padrão a serem usados ao iniciar o aplicativo:

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 esse Dockerfile com o ambiente flexível do App Engine, faça o seguinte:

  • Substitua OPTION1 e OPTION2 pelos valores de configuração do agente necessários para o aplicativo e substitua PATH_TO_YOUR_JAR_FILE pelo caminho para o arquivo jar.
  • Coloque o Dockerfile no mesmo diretório que o arquivo app.yaml.
  • Modifique seu arquivo app.yaml para especificar um ambiente de execução personalizado. Para mais informações, consulte Como criar ambientes de execução personalizados.

Ambiente padrão

Quando você usa o ambiente de execução do Java, o agente do Profiler é pré-instalado. Portanto, não há outras etapas necessárias para instalar o agente. Para o Java versão 11 e mais recentes, ele está pré-instalado em /opt/cprof.

Fora do Google Cloud

  1. Crie um diretório de instalação, por exemplo, /opt/cprof, para o agente do Profiler:

     sudo mkdir -p /opt/cprof

  2. Faça o download do arquivo do agente no repositório storage.googleapis.com e extraia-o no diretório de instalação:

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

Para listar todas as versões do agente disponíveis para download, execute o seguinte comando:

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

A resposta do comando é semelhante a esta:

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 fazer o download de uma versão específica do agente, transmita o URL para o comando de download. Por exemplo, para fazer o download do agente criado em 28 de outubro de 2019, use a seguinte declaração:

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

A versão do agente é registrada durante a inicialização.

Como carregar o agente Profiler

Para criar um perfil do seu aplicativo, inicie o Java normalmente para executar seu programa. No entanto, é preciso especificar as opções de configuração do agente. Determine o caminho para a biblioteca do agente para poder transmitir opções a ela.

No ambiente padrão do App Engine, o agente é automaticamente carregado e configurado. Pule para a seção Como iniciar o programa para ver detalhes sobre como configurar e iniciar o programa.

Configuração do agente

Para configurar o agente de criação de perfil, inclua a sinalização -agentpath ao iniciar o aplicativo:

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

Nesta expressão, INSTALL_DIR é o caminho para o agente de criação de perfil, enquanto OPTION1, OPTION2, e OPTION3 são opções de configuração do agente. Por exemplo, se você substituir OPTION1 por -cprof_service=myapp na expressão anterior, definirá o nome do serviço como myapp. Não há restrições quanto ao número de opções ou ao pedido. As opções de configuração compatíveis estão listadas na tabela a seguir:

Opção de agente Descrição
-cprof_service Se seu aplicativo não estiver em execução no App Engine, use esta opção de configuração para definir o nome do serviço. Para restrições de nome de serviço, consulte Argumentos de versão e nome do serviço.
-cprof_service_version Quando quiser analisar os dados de criação de perfil usando a IU do Profiler pela versão do serviço, use esta opção para definir a versão. Para restrições de versão, consulte Argumentos de versão e nome do serviço.
-cprof_project_id Quando você estiver executando fora do Google Cloud, use essa opção para especificar o ID do projeto do Google Cloud. Saiba mais em Como criar perfis de aplicativos em execução fora do Google Cloud.
-cprof_zone_name Quando seu aplicativo é executado no Google Cloud, o agente de criação de perfil determina a zona comunicando-se com o serviço de metadados do Compute Engine. Se o agente de criação de perfil não puder se comunicar com o serviço de metadados, será necessário usar esta opção.
-cprof_gce_metadata_server_retry_count
-cprof_gce_metadata_server_retry_sleep_sec
Juntas, essas duas opções definem a política de repetição que o agente profiler usa quando se comunica com o serviço de metadados do Compute Engine. para coletar o ID do projeto do Google Cloud e as informações da zona.

A política padrão é tentar novamente até três vezes, aguardando um segundo entre as tentativas. Essa política é suficiente para a maioria das configurações.
-cprof_cpu_use_per_thread_timers Para os perfis de tempo de CPU mais precisos, defina esta opção como verdadeira. O uso desta opção resulta em aumento da sobrecarga por linha de execução.

O valor padrão é falso.
-cprof_force_debug_non_safepoints Por padrão, o agente de criação de perfil força o JVM a gerar informações de depuração para todo o código gerado just in time (JIT), além de gerar informações de depuração para todos os pontos seguros. Isso resulta em informações mais precisas das funções e da localização no nível da linha para perfis de heap e de tempo da CPU à custa de sobrecarga extra do agente. É possível desativar a geração de informações de depuração para o código JIT, configurando esta opção como falsa.

O valor padrão é verdadeiro.
-cprof_wall_num_threads_cutoff Por padrão, os perfis de tempo decorrido não são coletados se o número total de linhas de execução no aplicativo exceder 4096. O limite garante que, durante a coleta de perfis, o custo de atravessar a pilha de linhas de execução seja mínimo. Se seu serviço normalmente tem mais de 4096 linhas de execução e se você quer coletar dados de criação de perfil à custa de sobrecarga extra, use essa sinalização para aumentar o limite.

O limite padrão é de 4096 linhas de execução.
-cprof_enable_heap_sampling Para ativar a criação de perfil de alocação heap para Java 11 e posterior, configure
-cprof_enable_heap_sampling=true. A criação de perfil por heap não é compatível com Java 10 e inferior.

A criação de perfil de alocação heap está desativada por padrão.

Quando você ativa a criação de perfil de alocação heap, o intervalo de amostragem é definido como 512 KiB por padrão. Ele é suficiente para a maioria dos aplicativos e incorre em menos de 0,5% de sobrecarga para o aplicativo. Intervalos de amostragem de 256 KiB (262144) a 1024 KiB (1048576) são compatíveis. Por exemplo, para definir o intervalo de amostragem para 256 KiB, o que duplica a taxa de amostragem, adicione a opção de agente:
-cprof_heap_sampling_interval=262144
Da mesma forma, para definir o intervalo de amostragem como 1024 KiB, o que reduz pela metade a taxa de amostragem, adicione a opção de agente:
-cprof_heap_sampling_interval=1048576
Se você ativar esse tipo de perfil, especifique uma nova versão do serviço ao implantar seu aplicativo. Para mais informações, consulte Por que não tenho dados para um tipo de perfil específico?

Argumentos de versão e nome de serviço

Ao carregar o agente do Profiler, você especifica um argumento de nome de serviço e um opcional de versão para configurá-lo.

Com o nome de serviço, o Profiler pode coletar dados de criação de perfil de todas as réplicas desse serviço. O criador de perfil garante uma taxa de coleta de um perfil por minuto, em média. Isso é para todos os nomes de serviço em cada combinação de zona e versão.

Por exemplo, se você tiver um serviço com duas versões executadas em réplicas em três zonas, o criador de perfil produzirá uma média de seis perfis por minuto para esse serviço.

Se você usar nomes de serviço diferentes nas réplicas, o serviço terá perfis criados com mais frequência do que o necessário, com uma sobrecarga correspondente maior.

Ao selecionar um nome de serviço:

  • escolha um que represente claramente o serviço na arquitetura do aplicativo. Essa seleção não é tão importante se você executa apenas um serviço ou aplicativo. Ela é mais importante se o aplicativo é executado como um conjunto de microsserviços, por exemplo;

  • não use nenhum valor específico do processo, como o código, na string do nome de serviço;

  • a string do nome de serviço precisa corresponder a esta expressão regular:

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

Uma boa diretriz é usar uma string estática como imageproc-service como o nome do serviço.

A versão de serviço é opcional. Se você especificá-la, o Profiler poderá agregar informações de criação de perfil de várias instâncias e exibi-las corretamente. É possível usá-la para marcar diferentes versões dos serviços conforme eles são implantados. Com a IU do Profiler, você filtra os dados por versão de serviço. Assim, é possível comparar o desempenho de versões mais antigas e mais recentes do código.

O valor do argumento da versão do serviço é uma string de formato livre. No entanto, os valores desse argumento geralmente se parecem com números de versão. Por exemplo, 1.0.0 ou 2.1.2.

Como iniciar o programa

Compute Engine

Inicie o Java normalmente para executar seu programa e especifique as opções de configuração do 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

Modifique o Dockerfile do contêiner de serviço para iniciar o Java normalmente e executar o programa. Depois, especifique as opções de configuração do 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 flexível

Modifique o arquivo de configuração app.yaml para definir a variável de ambiente PROFILER_ENABLE. Depois, inicie o programa normalmente:

env_variables:
   PROFILER_ENABLE: true

Consulte Como definir variáveis de ambiente para mais informações.

Ambiente padrão

Ambiente de execução do Java 21

Se você não usa serviços agrupados legados, ative a coleta de perfil modificando o arquivo app.yaml para especificar a flag agentpath usando um dos seguintes métodos:

  • Defina a variável de ambiente JAVA_TOOL_OPTIONS:

    runtime: java21
    env_variables:
      JAVA_TOOL_OPTIONS: "-agentpath:/opt/cprof/profiler_java_agent.so=-logtostderr,-cprof_enable_heap_sampling=true"
    
  • Especifique o agentpath usando o elemento entrypoint:

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

Se você usa serviços agrupados legados, ative a coleta de perfil modificando o arquivo appengine-web.xml para especificar a flag agentpath usando um dos seguintes métodos:

  • Defina a variável de 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>
  • Defina a variável de 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>
  • Especifique o agentpath usando o 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 um novo tipo de perfil estiver configurado para coleta, especifique uma nova versão de serviço ao implantar o aplicativo. Para mais informações, consulte Por que não tenho dados para um tipo de perfil específico?

Geração de registros do agente

O agente de criação de perfil pode relatar informações de geração de registros para o ambiente flexível do App Engine, Compute Engine e GKE. O agente de criação de perfil é compatível com os níveis de geração de registros a seguir:

  • 0: registra todas as mensagens. Nível de geração de registros padrão.
  • 1: aviso de registro, erro e mensagens fatais.
  • 2: erro de registro e mensagens fatais.
  • 3: registra apenas mensagens fatais e interrompe o aplicativo.

Para ativar a gravação de registros no erro padrão com o nível de geração de registros padrão, anexe -logtostderr à configuração -agentpath.

Para definir o nível de registro para que registre apenas mensagens fatais e de erro, anexe -minloglevel=2 à configuração -agentpath.

Por exemplo, para ativar a geração de registros de erros e mensagens fatais em erros padrão, anexe -logtostderr e ‑minloglevel=2 à configuração -agentpath:

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

Solução de problemas

Nesta seção, listamos problemas específicos da criação de perfil de aplicativos Java. Consulte Solução de problemas para conseguir ajuda com problemas comuns.

Comportamento Causa Solução
Você ativou vários criadores de perfil de alocação heap e não tem dados de perfil. O uso simultâneo de vários criadores de perfil de alocação heap desativa todo o suporte de criação desse tipo para Java. Essa é uma limitação da JVM. Ative um criador de perfil.

Como executar com o Alpine Linux

O agente de criação de perfil do Java para Alpine Linux é compatível apenas com as configurações do Google Kubernetes Engine.

Para instalar o agente de criação de perfil Java mais recente para Linux Alpine, consulte Como instalar o agente do Profiler.

Erro de autenticação

Se você usar imagens do Docker executadas com o Linux Alpine (como golang:alpine ou apenas alpine), você poderá encontrar o seguinte erro de autenticação:

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

Para ver o erro, você precisa ativar a geração de registros do agente.

O erro indica que as imagens do Docker com o Alpine Linux não têm os certificados SSL raiz instalados por padrão. Esses certificados são necessários para que o agente de criação de perfil se comunique com a API Profiler. Para resolver esse erro, adicione o seguinte comando apk ao seu Dockerfile:

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

Depois, será necessário recriar e reimplantar o aplicativo.

A seguir