単純な「hello world」レスポンスを返すだけでも、Envoy プロキシサーバーは内部処理により CPU コア全体を消費することがあります。このケーススタディでは、OpenResty XRay が生成した C++ CPU フレームグラフにより、実行中の Envoy プロセス内の 3 つの最もホットなコードパスが明らかになりました。その第 1 位は SchedulableCallbackImpl 演算子であり、バイナリの再起動やリコンパイルは一切不要です。スループット比較では、同一ハードウェア上で OpenResty が Envoy より 200% 以上多くのリクエストを処理していることも示されています。

以下に、完全なプロファイリングの手順、フレームグラフの解読、および自動レポート設定を紹介します。

シナリオ:Envoy プロセスの CPU 使用率が 90% 超

cat コマンドを使用して Envoy サーバーの設定ファイルを確認します。

cat コマンドで表示した Envoy サーバーの設定ファイル

ポート 1088 でリッスンしていることがわかります。

ポート 1088 でリッスンする Envoy 設定

“Hello world” というレスポンスボディを返しています。

hello world を返す Envoy ダイレクトレスポンス設定

/hello インターフェースのレスポンスをテストします。予想通り “Hello World” というレスポンスが返ってきます。

Envoy から hello world レスポンスを確認する curl 出力

top コマンドを実行して CPU 使用状況を確認します。envoy という名前のプロセスを見てみましょう。

top コマンド出力で Envoy プロセスの高 CPU 使用率を表示

CPU コアリソースの 90% 以上を消費していることがわかります。

CPU コアの 90% 以上を消費する Envoy プロセス

ps コマンドを実行してこのプロセスの完全なコマンドラインを確認します。これは Envoy の公式バイナリパッケージリポジトリからダウンロードしてインストールされたものです。

公式リポジトリからインストールされた Envoy バイナリパスを表示する ps コマンド

C++ フレームグラフによる Envoy CPU プロファイリング

実行中の Envoy プロセスをプロファイリング

OpenResty XRay の Web コンソールを開きます。このマシンのダッシュボードでは、CPU 使用率がほぼ 100% に達していることが表示され、実行中の Envoy アプリケーションが検出されています。

OpenResty XRay ダッシュボードに envoy-app-server の高 CPU 使用率を表示

「Guided Analysis」ページに移動し、問題タイプとして「High CPU usage」を選択します。次に、Envoy ワーカープロセスを選択します。top で確認した通り、CPU 使用率 93% と表示されています:

分析対象として CPU 使用率 93% の Envoy ワーカープロセスを選択

デフォルト設定(アプリケーションタイプ:Envoy、言語レベル:C/C++、最大実行時間:300 秒)のまま分析を開始します。2 ラウンドのサンプリング後、OpenResty XRay が自動的にレポートを生成し、最もホットな C++ コードパスをランキング表示します:

OpenResty XRay 分析レポートに Envoy の CPU ホットパスを表示

これが分析対象の問題タイプ、「CPU」です。

レポートが CPU を診断対象の問題タイプとして識別

第 1 ホットパス——SchedulableCallbackImpl

これは CPU 時間を最も消費している C++ コードパスです。

Envoy CPU レポートの第 1 位ホット C++ コードパス

これは SchedulableCallbackImpl クラスのオーバーロードされた演算子です。

SchedulableCallbackImpl のオーバーロード演算子が最大の CPU 消費者として特定

「More」をクリックして詳細を表示します。

ホットコードパスの詳細を展開

上記のホットコードパスは、この C++ 言語レベルの CPU フレームグラフから自動的に導き出されたものです。

SchedulableCallbackImpl ホットパスを示す Envoy プロセスの C++ CPU フレームグラフ

アイコンをクリックしてフレームグラフを拡大します。

詳細検査のために拡大された Envoy CPU フレームグラフ

この invoke_impl 関数を拡大します。

invoke_impl 関数にズームインしたフレームグラフ

Envoy のネットワーク socket クラスの write メソッドは、socket 書き込み操作を実行します。これは HTTP レスポンスデータを送信します。

Envoy socket write メソッドをハイライトしたフレームグラフ

Envoy バッファクラスの drain メソッドは、書き込みバッファ内の未使用メモリを解放し、その他のクリーンアップ作業を実行します。

書き込みバッファメモリを解放する buffer drain メソッドを示すフレームグラフ

Envoy ディスパッチャークラスの clearDeferredDeletedList メソッドは、現在のリクエストに関連するすべてのリソースを解放し、すべてのクリーンアップ作業を実行します。

Envoy ディスパッチャーの clearDeferredDeletedList クリーンアップを示すフレームグラフ

第 2 ホットパス——emitLog アクセスログフォーマット

CPU 時間消費量が 2 番目に多い C++ ホットコードパスを見てみましょう。

Envoy CPU レポートの第 2 位ホット C++ コードパス

Envoy プロキシの emitLog 関数は、アクセスログをファイルに書き込むために使用されます。

Envoy で 2 番目に CPU 集約的なパスとして特定された emitLog 関数

フレームグラフを拡大します。

emitLog コードパスの拡大フレームグラフ

この emitLog 関数を拡大します。

Envoy の emitLog 関数にズームインしたフレームグラフ

emitLog の CPU 時間の大部分は、ファイル書き込み操作ではなく、ログメッセージ文字列のフォーマットに使用されています。

emitLog の CPU 時間の大部分が文字列フォーマットに費やされていることを示すフレームグラフ

第 3 ホットパス——prepareLocalReplayViaFilterChain

これは CPU 時間を 3 番目に多く消費しているホットコードパスです。

Envoy CPU レポートの第 3 位ホット C++ コードパス

prepareLocalReplayViaFilterChain 関数は Envoy のレスポンス出力フィルターチェーンにあります。チェーン内の各フィルターがレスポンスを変更する可能性があります。

Envoy レスポンスフィルターチェーンの prepareLocalReplayViaFilterChain

フレームグラフを拡大します。

Envoy フィルターチェーンコードパスの拡大フレームグラフ

prepareLocalReplayViaFilterChain 関数を拡大します。

prepareLocalReplayViaFilterChain にズームインしたフレームグラフ

createHeaderMap 関数が何度も呼び出されています。これは主に HTTP ヘッダー用の新しいハッシュテーブルを割り当てるために使用されます。

HTTP ヘッダー用ハッシュテーブルを割り当てる createHeaderMap を示すフレームグラフ

newUri 関数は主に URI 文字列の割り当てとフォーマットに使用されます。

URI 文字列を割り当てフォーマットする newUri を示すフレームグラフ

setStatus 関数はレスポンスステータスコードを設定するために使用されます。

レスポンスステータスコードを設定する setStatus を示すフレームグラフ

BodyFormatter クラスの format メソッドは、レスポンスボディデータをフォーマットするために使用されます。

レスポンスボディをフォーマットする BodyFormatter を示すフレームグラフ

setContentLength メソッドもレスポンス長ヘッダーを設定するために使用されます。

レスポンス長ヘッダーを設定する setContentLength を示すフレームグラフ

setReferenceContentType メソッドは Content-Type レスポンスヘッダーを設定するために使用されます。

Content-Type ヘッダーを設定する setReferenceContentType を示すフレームグラフ

Envoy と OpenResty のスループット比較

これは Envoy サーバーと OpenResty のパフォーマンス比較チャートです。OpenResty のスループットが Envoy サーバーよりも 200% 以上高いことがわかります。

OpenResty が Envoy より 200% 以上高速であることを示すスループット比較チャート

自動化レポートによる継続的 CPU 監視

OpenResty XRay は、オンラインプロセスを自動的に監視し、分析レポートを表示することもできます。「Insights」ページに切り替えます。

自動化 CPU レポート用の OpenResty XRay Insights ページ

「Insights」ページでは、日次および週次のレポートを確認することができます。

Insights ページの日次および週次 CPU プロファイリングレポート

したがって、「Guided Analysis」機能を必ずしも使用する必要はありません。もちろん、「Guided Analysis」はアプリケーションの開発やデモンストレーションに非常に有用です。

開発およびデモンストレーション用の Guided Analysis オプション

OpenResty XRay について

OpenResty XRay動的トレーシング製品であり、実行中のアプリケーションを自動的に分析して、パフォーマンスの問題、動作の問題、セキュリティの脆弱性を解決し、実行可能な提案を提供いたします。基盤となる実装において、OpenResty XRay は弊社の Y 言語によって駆動され、Stap+、eBPF+、GDB、ODB など、様々な環境下で複数の異なるランタイムをサポートしております。

このチュートリアルがお役に立ちましたら、当ブログや弊社の YouTube チャンネルのご購読をご検討ください。ありがとうございます!

FAQ:Envoy CPU プロファイリング

Envoy プロキシの CPU 使用率が高いのはなぜですか?

このケーススタディのフレームグラフが明らかにした一般的な CPU 消費要因:socket 書き込みコールバックとバッファクリーンアップ(SchedulableCallbackImpl)、アクセスログ文字列フォーマット(emitLog)、および HTTP ヘッダーハッシュテーブル割り当てを含むレスポンスフィルターチェーン処理(prepareLocalReplayViaFilterChain)。メトリクスから推測するのではなく、CPU フレームグラフで実行中のプロセスをプロファイリングすることで、実際にどの C++ コードパスが CPU を支配しているかを正確に特定できます。

Envoy の CPU フレームグラフを生成するには?

ダイナミックトレーシングプロファイラーを Envoy ワーカープロセスの PID に向けて実行します。OpenResty XRay の Guided Analysis は実行中のバイナリをサンプリングし、C 言語レベルの CPU フレームグラフを生成し、最もホットな C++ コードパスを自動的にランク付けします。リコンパイル、再起動、計装は一切不要です。代替手段として gperftools で Envoy を再ビルドして pprof を使用する方法もありますが、ソースコードへのアクセスとサービスの再起動が必要です。

再起動なしで本番環境の Envoy CPU をプロファイリングできますか?

はい。ダイナミックトレーシングツールは、Linux の uprobes および kprobes を介して、厳密な読み取り専用方式で実行中のプロセスにアタッチします。ターゲットプロセスにバイトコードは一切注入されず、サンプリングオーバーヘッドは無視できるレベルです。レイテンシーに敏感な本番環境での展開にも安全に使用できます。

著者について

章亦春(Zhang Yichun)は、オープンソースの OpenResty® プロジェクトの創始者であり、OpenResty Inc. の CEO および創業者です。

章亦春(GitHub ID: agentzh)は中国江蘇省生まれで、現在は米国ベイエリアに在住しております。彼は中国における初期のオープンソース技術と文化の提唱者およびリーダーの一人であり、Cloudflare、Yahoo!、Alibaba など、国際的に有名なハイテク企業に勤務した経験があります。「エッジコンピューティング」、「動的トレーシング」、「機械プログラミング」 の先駆者であり、22 年以上のプログラミング経験と 16 年以上のオープンソース経験を持っております。世界中で 4000 万以上のドメイン名を持つユーザーを抱えるオープンソースプロジェクトのリーダーとして、彼は OpenResty® オープンソースプロジェクトをベースに、米国シリコンバレーの中心部にハイテク企業 OpenResty Inc. を設立いたしました。同社の主力製品である OpenResty XRay動的トレーシング技術を利用した非侵襲的な障害分析および排除ツール)と OpenResty Edge(マイクロサービスおよび分散トラフィックに最適化された多機能ゲートウェイソフトウェア)は、世界中の多くの上場企業および大企業から高い評価を得ております。OpenResty 以外にも、章亦春は Linux カーネル、Nginx、LuaJITGDBSystemTapLLVM、Perl など、複数のオープンソースプロジェクトに累計 100 万行以上のコードを寄与し、60 以上のオープンソースソフトウェアライブラリを執筆しております。

翻訳

英語版の原文と日本語訳版(本文)をご用意しております。読者の皆様による他の言語への翻訳版も歓迎いたします。全文翻訳で省略がなければ、採用を検討させていただきます。心より感謝申し上げます!