Kong プラグインの CPU 高騰:pcall に隠れた Lua 例外をフレームグラフで特定
Kong のカスタムプラグインは、Lua 例外を繰り返しスローすると、トラフィックが高くなくても CPU を使い果たすことがあります。あるお客様の auth プラグインでは、nil 値が string.lower に渡されて例外が繰り返し発生していました。しかもそれは pcall に飲み込まれていたため、Kong のエラーログには何も表示されませんでした。OpenResty XRay の CPU フレームグラフがこれを handler.lua:35 で特定し、簡単な修正で CPU は 80% から 50% に下がりました。
以下では、その追跡手順をご紹介します。Kong は、オープンソース OpenResty ソフトウェアをベースに開発された強力で柔軟性の高い API ゲートウェイですが、それを拡張するカスタムプラグインが、発見・デバッグの難しいパフォーマンス問題を引き起こすことがあります。OpenResty XRay は、コードを変更したりプロセスを再起動したりすることなく、Kong を含むあらゆる OpenResty アプリケーションを監視・分析できる非侵入型のツールです。
問題:トラフィックは低いのに Kong プラグインの CPU が高騰
当社のお客様は、受信する API トラフィックがそれほど高くないにもかかわらず、Kong サーバーが予想以上に CPU リソースを消費していることに気づきました。カスタムプラグインに何らかの非効率性やエラーがある可能性を疑いましたが、どこから調査を始めればよいかわかりませんでした。CPU ボトルネックの根本原因を特定し、問題解決のための実行可能な提案を提供できるツールが必要でした。(各 Kong プラグインがそれぞれどれだけ CPU とメモリを消費するかを俯瞰したい場合は、姉妹記事の プラグイン別 CPU・メモリ統計 をご覧ください。)
OpenResty XRay のフレームグラフによる CPU ボトルネックの特定
お客様は Kong サーバーに OpenResty XRay をインストールし、定期的に、または CPU 使用率が急増した際に、実行中の Kong プロセスを自動的にサンプリングするよう設定しました。OpenResty XRay は、その日の分析レポートを毎時自動更新するため、お客様と当社のチームは最新のパフォーマンスデータを確認することができました。
レポートで最初に注目したのは、CPU セクションの以下のホットコードパスでした:
このコードパスは、入力文字列のすべての文字を小文字に変換する string.lower 標準関数が Lua 例外をスローしていることを示しています。例外は、ほとんどのプログラミング言語とその実装において高コストの操作です。通常、スタックの巻き戻しとエラー処理が必要となるためです。これらの例外がどのように発生し、どこから来ているのかを知りたいと思いました。
コードパス内の Lua または C 関数にマウスカーソルを合わせると、ファイル名と行番号を含む Lua のソース位置を確認できます。
レポートには CPU フレームグラフも表示され、このホットコードパスが赤色で強調表示されています:
発見を確認するため、同じレポートの「エラーと例外」セクションも確認しました。そこには以下のエラーメッセージが表示されていました:
エラーメッセージには "bad argument #1 to 'lower' (string expected, got nil)" と表示されており、Lua コードが lower 関数に nil 値を渡していることを示しています。この関数が期待するのは文字列型の引数です。親関数フレーム [builtin#string.lower] を見ることで、これが Lua の組み込み関数 string.lower であることがわかります。レポートから、この例外がソースファイル .../kong/plugins/auth/handler.lua の 35 行目からスローされていることもわかりました。
興味深いことに、この Lua 例外は実際には pcall によってキャッチされています。pcall は別の関数を保護モードで呼び出す Lua 関数で、Lua ハンドラ全体を中断することなくエラーをキャッチできます。これが、Kong のエラーログファイルに有用な情報が見つからなかった理由です。
この時点で、お客様独自の auth Kong プラグインに、標準 Lua API 関数 string.lower を誤用しているバグがあると結論づけるのに十分な情報がありました。修正方法も簡単です:.../kong/plugins/auth/handler.lua の 35 行目の string.lower に nil 値を渡すのを避けるだけです。
結果:Kong の CPU 使用率が 80% から 50% に低下
カスタム auth プラグインを修正した後、お客様は Kong サーバーのパフォーマンスが大幅に向上したことを確認しました。
グラフから、同じ API トラフィック下で、CPU の平均使用率が 80% から 50% へ低下したことがわかります。CPU リソースの消費が 37.5% 減少しました!お客様はこの結果に非常に満足し、当社の支援に感謝の意を表しました。
よくある質問
なぜ Kong プラグインの CPU が高くなるのですか?
トラフィックが高くなくても、カスタム Kong プラグインが Lua 例外を繰り返しスローすると CPU を使い果たすことがあります。例外はスタックの巻き戻しとエラー処理を必要とするため、高コストの操作です。本事例では、auth プラグインが nil 値を string.lower に繰り返し渡し、その都度例外を発生させ、トラフィックだけでは説明できない CPU を消費していました。
どの Kong プラグインが CPU を消費しているかを特定するには?
OpenResty XRay は、実行中の Kong ワーカープロセスを、コードを変更したり再起動したりせずにサンプリングし、CPU セクションのホットコードパス、CPU フレームグラフ、そして正確な Lua ソースファイルと行番号を表示します。本事例では、お客様自身の auth プラグイン内の string.lower(handler.lua:35)にホットパスを特定しました。
pcall でキャッチされた Lua 例外でも CPU が高くなりますか?
はい。pcall は関数を保護モードで実行してエラーをキャッチするため、Kong のエラーログには何も表示されません。しかし例外は発生するたびにスローされスタックが巻き戻されるため、CPU を消費し続けます。これが、問題がログには現れず、フレームグラフが明らかにするまで見えなかった理由です。
結論
この記事では、OpenResty XRay がお客様のカスタム Kong プラグインにおける予期せぬ Lua 例外による CPU ボトルネックの発見と修正をどのように支援したかを示しました。OpenResty XRay を使用することで、ホットコードパスと例外のソース位置、エラーメッセージとスタックトレースを迅速に特定することができました。また、修正後のパフォーマンス改善も確認できました。
OpenResty XRay は動的トレーシング製品で、実行中のアプリケーションを自動的に分析し、パフォーマンスの問題、動作の問題、セキュリティの脆弱性を排除し、実行可能な提案を提供します。基盤となる実装では、OpenResty XRay は当社の Y 言語によって駆動され、Stap+、eBPF+、GDB、ODB など、さまざまな環境下で複数の異なるランタイムをサポートしています。
OpenResty XRay について
OpenResty XRay は動的トレーシング製品であり、実行中のアプリケーションを自動的に分析して、パフォーマンスの問題、動作の問題、セキュリティの脆弱性を排除し、実行可能な提案を提供します。基盤となる実装では、OpenResty XRay は当社の Y 言語によって駆動され、Stap+、eBPF+、GDB、ODB など、さまざまな環境下で複数の異なるランタイムをサポートしています。
著者について
章亦春(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、LuaJIT、GDB、SystemTap、LLVM、Perl など、複数のオープンソースプロジェクトに累計 100 万行以上のコードを寄与し、60 以上のオープンソースソフトウェアライブラリを執筆しております。
翻訳
英語版の原文と日本語訳版(本文)をご用意しております。読者の皆様による他の言語への翻訳版も歓迎いたします。全文翻訳で省略がなければ、採用を検討させていただきます。心より感謝申し上げます!





















