AWS Lambdaのパフォーマンス改善(2)

2024.03.27
マルチクラウド 技術 AWS クラウド活用 パフォーマンス改善
AWS Lambdaのパフォーマンス改善(2)

はじめに

こんにちは。技術本部 アーキテクチャ&テクノロジー部の髙橋 洋樹です。AWS Lambdaをテーマに投稿している本ブログシリーズ。前回はパフォーマンス改善に欠かすことができない「効果測定」に役立つサービスのご紹介と、INITフェーズのパフォーマンス改善方法についてご紹介しました。まだお読みでない方は、ぜひこちらからご覧ください。
さて今回は、AWS LambdaのライフサイクルでINITフェーズの次にくるINVOKEフェーズのパフォーマンス改善方法を中心に説明していきます。各フェーズの説明はAWS Lambdaの仕組みを紹介した「サーバレス時代の必須技術、AWS Lambdaを知ろう」ブログで解説しているので、忘れてしまった方は立ち返ってみてください。

INVOKEフェーズのパフォーマンスを改善

INVOKEフェーズのパフォーマンスを改善する場合、ハンドラー内の具体的にどの部分でどの位の処理時間がかかっているのかを計測する必要があります。しかし、前回の「AWS Lambdaのパフォーマンス改善(1)」ブログでご紹介したAWS X-Rayのアクティビティトレースだけでは、そこまでの分析が難しいため、AWS X-RayのSDKモジュールを追加で利用する必要があります。使用イメージは以下の通りです。

画面:AWS X-RayのSDKモジュールインポート

画面:AWS X-RayのSDKモジュールインポート

AWS X-RayのSDKモジュールについて、使い方の詳細はAWS X-Rayのデベロッパーガイドを参照ください。では、パフォーマンス改善の可能性がある方法をいくつか紹介していきます。

再利用できる処理をハンドラー外に定義する

以前掲載した「サーバレス時代の必須技術、AWS Lambdaを知ろう」ブログの中で述べた通り、ハンドラー外に定義されたコードはINITフェーズで実行されます。そのため、ハンドラー外に一度初期化すれば次の呼び出しでもそのまま利用できるもの、例えば、データベースのコネクションなどを生成しておくことでINVOKEフェーズの高速化が期待できます。

画面:ハンドラー外での処理の定義

画面:ハンドラー外での処理の定義

逆に言うと、呼び出し間で共有したくないものをハンドラー外で定義するのは避けましょう。例えば、ハンドラー内で呼び出された時刻を利用したい場合に、ハンドラー外で呼び出し時刻を取得して利用するなどは避けましょう。

アーキテクチャを見直す

1つのAWS Lambda関数内で多くの処理を実行している場合、処理を分割し非同期的に実施するようにアーキテクチャを見直すことでパフォーマンスの改善が見込むことができます。2つほど例をあげましょう。

例1

まず以下に示す例ではAWS Lambda関数が内部にループ処理を持っており、ループの内部では1分かかる処理が実行されています。ループの要素数はAmazon EC2インスタンスの数に依存するため、インスタンスの数が多くなるとハンドラーの最大実行時間である15分を超えてしまうことが予想できます。ループ内の処理について時間の短縮が難しい場合、どのような改善案が考えられるでしょうか。

アーキテクチャの見直し1(改善前)

アーキテクチャの見直し1(改善前)

この場合、ハンドラー自身がループを逐次処理していることが原因であるため、これを非同期に並列処理するように変更しましょう。具体的には、AWS Step Functionsの動的並列実行の機能を利用します。始めのタスクでAmazon EC2インスタンスの一覧を直接取得します。そして続くタスクでLambda関数を並列実行する流れになります。別の案としては、ハンドラー内で処理を非同期実行することも考えられますが、管理性という観点ではAWS Step Functionsを使用した構成にすることをお勧めします。

アーキテクチャの見直し1(改善後)

アーキテクチャの見直し1(改善後)

例2

次の例では、クライアント端末からAPI Gateway経由でLambda関数が同期的に呼び出されています。つまりハンドラー内のコードが完了してからクライアントにレスポンスが返されている状態です。そしてLambda関数はAmazon AuroraとSecrets Managerを呼び出しています。この状態でAPI GatewayとLambda関数の間、Lambda関数とSecrets Managerの間でスロットリングが発生しています。サービスの上限を引き上げる以外の手段だと、どのような改善案が考えられるでしょうか。

アーキテクチャの見直し2(改善前)

アーキテクチャの見直し2(改善前)

改善案は色々考えられると思いますが、一例として次のようなアプローチが考えられます。まずAPI GatewayとLambdaの間にSQSを挟みます。そしてLambda側では同時実行数を予約しておき、Secrets Managerのスロットリングを回避します。クライアントのリクエストが発生した場合、API GatewayはSQSにリクエストをPush後、クライアントにレスポンス(HTTP 202)を返します。その際、クライアントとの間でWebSocketの接続を確立しておきます。Lambda関数はキューを取得して、Amazon Auroraを更新します。更新完了後、Lambda関数はWebSocket経由で結果をクライアントに返却します。

アーキテクチャの見直し2(改善後)

アーキテクチャの見直し2(改善後)

メモリの増強

コールドスタートの所で述べた通り、高いメモリを割り当てるほどCPUのスペックも上がるのでハンドラー内の処理についても高速化が期待できます。一方でこれも先述の通り、時間単価が高くなります。

では一番コストパフォーマンスのよいメモリの割当量はどのように知ればよいでしょうか。主に2つ方法があります。1つ目は、AWS Compute Optimizerを利用する方法です。

画面:AWS Compute Optimizerの推奨画面

画面:AWS Compute Optimizerの推奨画面

AWS Compute Optimizerを利用すると、Lambda関数の過去の利用状況を分析して適切と思われるスペックを推奨してくれます。過去7日分の利用状況に基づいた分析であれば無料です。

画面:AWS Lambda Power Tuning

画面:AWS Lambda Power Tuning

2つ目はAWS Lambda Power Tuningというツールを利用する方法です。本ツールは異なるメモリ量を持つLambda関数をAWS Step Functionsで同時実行します。そして、横軸をメモリ量、縦軸を実行時間および総コストとするグラフを出力できます。

おわりに

さて、今回はAWS Lambdaのパフォーマンス改善にあたり、INVOKEフェーズのパフォーマンス改善方法についてご紹介しました。紹介したパーマンス改善方法のパターンを表にまとめると下記のようになります。

横にスクロールできます

改善方法 概要
再利用できる処理を
ハンドラー外に定義
ウォームスタート時に、再利用可能な処理をハンドラー外に記述する
アーキテクチャの見直し アーキテクチャの処理を分割し、非同期に実施するようにする
メモリの増強 適切なメモリ量の分析には、AWS Compute OptimizerやAWS Lambda Power Tuningを活用する

これまで、AWS LambdaのINVOKEフェーズの改善を中心に説明してきました。今回のブログテーマはいかがだったでしょうか?本シリーズが、少しでも皆様のAWS Lambda活用の役に立てば嬉しいです。また、当社では、AWSサービスの表面的な技術ノウハウに留まらず、サービスの裏側の仕組みまでを踏まえた上で、アプリケーションやアーキテクチャの改善提案をしております。AWS包括的技術支援サービスを提供しておりますので、AWS Lambdaのパフォーマンス改善に限らず、何かお困りごとがあればお気軽にお問い合わせください!それでは、近いうちにまた別のトピックでお会いしましょう!

関連ページ

おすすめブログ

5分でわかる、AWS Well-Architected Frameworkの要点(1)
5分でわかる、AWS Well-Architected Frameworkの要点(1)
今回は、AWS Well-Architected Frameworkについてです。私自身がAWS主催のAWS Well-Architected Partner Program Bootcampに参加することになったため、その予習も兼ねて内容をまとめ、前後編に渡ってお伝えしていきます。主にAWSの導入をご検討中の方、これから設計を進められようとしている方に読んでいただくとお役に立つのではと思います。AWS Well-Architected Frameworkはかなり重厚なドキュメントで、初めて触れる方は少しとっつきにくいかもしれませんので、本ブログを入口として理解を深めていっていただけたら幸いです。
サーバレス時代の必須技術、AWS Lambdaを知ろう
サーバレス時代の必須技術、AWS Lambdaを知ろう
最近AWS Lambdaの性能が課題となる相談を耳にすることが増えてきた気がします。これまでLambdaのパフォーマンスまで意識したことがなかったと思い、同じようにAWS Lambdaをなんとなく使用しているエンジニアの方に向けて、私自身の学びを基礎も含めて共有していければと思いました。そこで、今回はAWS Lambdaの基礎について、次回・次々回ではLambdaのパフォーマンス改善についてブログを投稿していきたいと思います。