Java コードのプロファイリング

このページでは、Java コードのプロファイリング用に Stackdriver Profiler を設定する方法について説明します。Java の場合、Profiler は CPU、ヒープ、経過時間のプロファイリングを行います。詳しくは、プロファイリングのコンセプトをご覧ください。

OpenJDK または Oracle JDK のいずれかのバージョン 7、8、9 または 11 を使用する必要があります。

Profiler の設定では通常、プロファイリング エージェントをインストールして、Java の起動時にそれを読み込み、エージェントの構成値を引数として渡します。Java を使用している場合、次の環境の Linux でプロファイリング エージェントを使用できます。

  • Compute Engine
  • Google Kubernetes Engine
  • App Engine フレキシブル環境
  • App Engine スタンダード環境(App Engine SDK バージョン 1.9.64 以降が必要)

Google Cloud Platform 以外のシステムでも Java コードをプロファイリングできます。詳細については、Google Cloud Platform の外部で実行されるコードのプロファイリングをご覧ください。

Profiler API を有効にする

プロファイリング エージェントを使用する前に、基盤となる Profiler API が有効になっている必要があります。Cloud SDK gcloud コマンドライン ツールまたは Cloud Console で API のステータスを確認し、無効になっている場合は有効にしてください。

Cloud SDK

  1. ワークステーションに Cloud SDK がまだインストールされていない場合は、Google Cloud SDK をご覧ください。

  2. 次のコマンドを実行します。

    gcloud services enable cloudprofiler.googleapis.com
    

詳細については、gcloud services をご覧ください。

Cloud Console

  1. [API とサービス] ダッシュボードに移動します。

    [API とサービス] に移動

  2. API へのアクセスで使用するプロジェクトを選択します。

  3. [API とサービスを追加] ボタンをクリックします。

    API とサービスの追加

  4. Profiler API を検索します。

  5. 検索結果で、Stackdriver Profiler API を選択します。

  6. [API が有効です] が表示されている場合、API はすでに有効になっています。そうでない場合は、[有効にする] ボタンをクリックします。

Profiler エージェントをインストールする

Compute Engine

Profiler をインストールするディレクトリを作成します(たとえば、/opt/cprof)。

sudo mkdir -p /opt/cprof

storage.googleapis.com リポジトリからエージェント アーカイブをダウンロードし、インストール ディレクトリに展開します。

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

GKE

GKE の場合、サービス コンテナの Dockerfile を変更して Profiler のインストール ディレクトリを作成し、エージェント アーカイブをダウンロードしてインストール ディレクトリに展開します。

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

App Engine フレキシブル環境

Google Java 8 と Java 9 ベースイメージを使用する場合、Profiler エージェントはプリインストールされています。これ以外のソースのベースイメージを使用する場合や別のサポート対象バージョンの Java を使用する場合は、エージェントをインストールする必要があります。

たとえば、Java 11 アプリケーション用の次の Dockerfile では、openjdk:11-slim イメージが読み込まれ、Profiler エージェントがインストールされます。

FROM openjdk:11-slim

COPY . .
RUN apt-get update && apt-get install -y curl wget

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

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

App Engine スタンダード環境

Google Java 8 ランタイム ベースイメージを使用する場合、Profiler エージェントはプリインストールされています。これ以外のソースのベースイメージを使用する場合や別のサポート対象バージョンの Java を使用する場合は、エージェントをインストールする必要があります。

たとえば、Java 11 アプリケーション用の次の Dockerfile では、openjdk:11-slim イメージが読み込まれ、Profiler エージェントがインストールされます。

FROM openjdk:11-slim

COPY . .
RUN apt-get update && apt-get install -y curl wget

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

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

Profiler エージェントを読み込む

コードをプロファイリングするには、自身のプログラムを実行する場合と同じように Java を起動します。ただし、エージェント構成オプションを指定します。エージェント ライブラリのパスを指定し、ライブラリにオプションを渡します。

App Engine スタンダード環境の場合、エージェントは自動的に読み込まれ、構成されます。プログラムを起動するに進んで、プログラムの構成と起動を行ってください。

エージェントの構成

-agentpath オプションを使用して、インストール ディレクトリにあるエージェント ライブラリのパスを指定し、追加の構成をライブラリに渡します。

構文は次のとおりです。

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

最も一般的なオプションは次のとおりです。

  • -cprof_service: プロファイリングされるサービスの名前。名前に関する制限については、サービス名とバージョンの引数をご覧ください。
  • -cprof_service_version: (任意)プロファイリングされるサービスのバージョン。
  • -cprof_gce_metadata_server_retry_count:(任意)エージェントが GCP メタデータ サーバーへの接続を再試行する最大回数。デフォルトでは、エージェントは再試行を行いません。エージェントが GCP メタデータ サーバーに接続できない場合、エージェントの初期化は失敗し、プロファイル データを利用できません。
  • -cprof_gce_metadata_server_retry_sleep_sec:(任意)エージェントによる再試行の実施間隔(秒数)。

コードをプロファイリングするには、通常の Java 呼び出しに -agentpath 構成を追加します。たとえば、myApp.jar を実行してプロファイリングする場合、最小限の呼び出しは次のようになります。

java -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myapp -jar myApp.jar

myApp.jar を実行し、5 秒間隔で 100 回まで GCP メタデータ サーバーとの接続を再試行するようエージェントに指示する場合、最小限の呼び出しは次のようになります。

java -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myapp,-cprof_gce_metadata_server_retry_sleep_sec=5,-cprof_gce_metadata_server_retry_count=100 -jar myApp.jar

ヒープ プロファイリング

Java 11 のヒープ プロファイリングを有効にするには、-agentpath-cprof_enable_heap_sampling を追加します。たとえば、myapp.jar を実行して、ヒープ プロファイリングを有効にしてプロファイリングを行う場合、呼び出しは次のようになります。

 java -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myapp,-cprof_enable_heap_sampling -jar myapp.jar

既知のバグやバグの報告方法については、Stackdriver プロダクトにバグが見つかった場合をご覧ください。

サービス名とバージョンの引数

Profiler エージェントを読み込むときに、service-name 引数とオプションの service-version 引数を指定して構成します。

Profiler は、サービス名で指定されたサービスのすべてのレプリカからプロファイリング データを収集します。Profiler サービスは、サービス バージョンとゾーンの組み合わせに対して、1 つのサービス名について平均で 1 分あたり 1 個のプロファイルを作成します。

たとえば、1 つのサービスの 2 つのバージョンが 3 つのゾーンのレプリカで実行されている場合、Profiler はそのサービスについて 1 分あたり平均で 6 個のプロファイルを作成します。

レプリカで異なるサービス名を使用している場合、サービスが必要以上にプロファイリングされるため、オーバーヘッドが大きくなります。

サービス名を選択する場合は、次の点に注意してください。

  • アプリケーション アーキテクチャでサービスを明確に識別できる名前を選択してください。1 つのサービスまたはアプリケーションしか実行していない場合は、どのようなサービス名を選択するかはさほど問題になりません。しかし、アプリケーションが一連のマイクロサービスとして実行されている場合は、名前の選択は重要になります。

  • service-name 文字列で、プロセス ID などのプロセス固有の値を使用しないでください。

  • service-name 文字列は次の正規表現と一致する必要があります。

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

サービス名として imageproc-service のような静的文字列を使用することをおすすめします。

サービス バージョンは省略可能です。サービス バージョンを指定すると、複数のインスタンスからプロファイリング情報が集約され、バージョンごとに表示されます。これは、複数のバージョンがデプロイされているときの識別に役立ちます。Profiler UI では、データをサービス バージョンでフィルタできます。これにより、コードの新旧バージョンのパフォーマンスを比較できます。

service-version 引数には、自由形式の文字列を指定できますが、通常は、バージョン番号のような値を使用します(例: 1.0.02.1.2)。

プログラムを起動する

Compute Engine

自身のプログラムを実行する場合と同じように Java を起動し、エージェント構成オプションを追加します。

java \
    -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myservice,-cprof_service_version=1.0.0 \
    [JAVA OPTIONS] -jar PATH/TO/YOUR/JARFILE [PROGRAM OPTIONS]

GKE

サービス コンテナの Dockerfile を変更して、自身のプログラムを実行する場合と同じように Java を起動し、エージェント構成オプションを追加します。

RUN java \
    -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myservice,-cprof_service_version=1.0.0 \
    [JAVA OPTIONS] -jar PATH/TO/YOUR/JARFILE [PROGRAM OPTIONS]

App Engine フレキシブル環境

app.yaml 構成ファイルを修正して、PROFILER_ENABLE 環境変数を設定します。いつもどおりプログラムを起動します。

env_variables:
   PROFILER_ENABLE: true

詳しくは、環境変数の定義をご覧ください。

App Engine スタンダード環境

app.yaml または appengine-web.xml 構成ファイルを変更して、GAE_PROFILER_MODE 環境変数を追加します。これにより、同じデプロイのすべてのインスタンスについて、平均で 1 分間に 1 回、CPU プロファイルとヒープ プロファイルを収集するように Profiler に指示します。

app.yaml:

env_variables:
   GAE_PROFILER_MODE: cpu,heap

appengine-web.xml:

  <env-variables>
    <env-var name="GAE_PROFILER_MODE" value="cpu,heap" />
  </env-variables>

その後、通常どおりプログラムを起動します。

詳しくは、環境変数の定義をご覧ください。

エージェント ロギング

プロファイリング エージェントは、App Engine フレキシブル環境、Compute Engine、GKE に関するロギング情報を報告できます。サポートされているロギングレベルは次のとおりです。

  • 0: すべてのメッセージをログに記録します。デフォルトのロギングレベルです。
  • 1: 警告メッセージ、エラー メッセージ、致命的問題のメッセージをログに記録します。
  • 2: エラー メッセージと致命的問題のメッセージをログに記録します。
  • 3: 致命的問題のメッセージだけをログに記録してアプリケーションを停止します。

デフォルトのロギングレベルで標準エラーにログを書き込めるようにするには、-agentpath 構成に -logtostderr を追加します。

エラー メッセージと致命的問題のメッセージだけをログに記録するようロギングレベルを設定するには、-agentpath 構成に -minloglevel=2 を追加します。

たとえば、エラー メッセージと致命的問題のメッセージを標準エラーに記録できるようにするには、-agentpath 構成に -logtostderr‑minloglevel=2 を追加します。

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

次のステップ

Stackdriver Profiler インターフェースの使用で Profiler のグラフとコントロールについて学習します。詳細については、以下をご覧ください。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。