Amazon Neptune での AWS Lambda 関数の使用 - Amazon Neptune

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

Amazon Neptune での AWS Lambda 関数の使用

AWS Lambda 関数は、Amazon Neptune アプリケーションで多くの用途があります。ここでは、一般的な Gremlin ドライバーと言語バリアントのいずれかで Lambda 関数を使用するための一般的なガイダンスと、Java、 JavaScriptおよび Python で記述された Lambda 関数の具体的な例を示します。

注記

Neptune で Lambda 関数を使用する最良の方法は、最近のエンジンリリースで変更されました。Neptune では、Lambda 実行コンテキストがリサイクルされた後接続をずっとアイドル状態で開いたままとなり、サーバー上のリソースリークを引き起こす可能性がありました。これを軽減するために、以前は各 Lambda 呼び出しで接続を開いたり閉じたりすることを推奨していました。ただし、エンジンバージョン 1.0.3.0 以降では、非アクティブな Lambda 実行コンテキストがリサイクルされた後で接続がリークしないように、アイドル接続タイムアウトが減少しました。そのため、実行コンテキストの間は 1 つの接続を使用することをお勧めします。これには、予期せず閉じられた接続を処理するためのエラー処理と back-off-and-retry 定型コードが含まれている必要があります。

AWS Lambda 関数での Gremlin WebSocket 接続の管理

Gremlin 言語バリアントを使用して Neptune をクエリする場合、ドライバーは WebSocket 接続を使用してデータベースに接続します。 WebSockets は、存続期間の長いクライアント/サーバー接続シナリオをサポートするように設計されています。一方、 は AWS Lambda、比較的短期間のステートレス実行をサポートするように設計されています。設計哲学におけるこの不一致は、Lambda を使用して Neptune を照会するときに予期しない問題が発生する可能性があります。

AWS Lambda 関数は、その関数を他の関数から分離する実行コンテキストで実行されます。実行コンテキストは、関数が最初に呼び出されたときに作成され、同じ関数の後続の呼び出しで再利用できます。

ただし、1 つの実行コンテキストは、関数の複数の同時呼び出しを処理するために使用されることはありません。関数が複数のクライアントによって同時に呼び出された場合、Lambda は関数のインスタンスごとに追加の実行コンテキストをスピンアップします。これらの新しい実行コンテキストはすべて、関数のそれ以降の呼び出しに対して再利用されます。

ある時点で、Lambda は実行コンテキストをリサイクルします。特にしばらく非アクティブになっている場合、 は、Lambda 拡張機能 を通じて、Init、、 Invoke Shutdownフェーズを含む実行コンテキストのライフサイクル AWS Lambda を公開します。 https://docs.aws.amazon.com/lambda/latest/dg/using-extensions.htmlこれらの拡張機能を使用すると、実行コンテキストがリサイクルされたときにデータベース接続などの外部リソースをクリーンアップするコードを記述できます。

一般的なベストプラクティスは、ハンドラ呼び出しごとに再利用できるようにLambda ハンドラー関数の外部でデータベース接続を開きます。ある時点でデータベース接続が切断された場合は、ハンドラ内から再接続できます。ただし、この方法では接続リークの危険性があります。実行コンテキストが破棄されてから接続がアイドル状態で長く開いたままの場合、断続的またはバースト的な Lambda 呼び出しシナリオでは、徐々に接続がリークされ、データベースリソースが枯渇する可能性があります。

Neptune の接続制限と接続タイムアウトは、新しいエンジンリリースで変更されました。以前は、すべてのインスタンスが最大 60,000 WebSocket の接続をサポートしていました。現在、Neptune インスタンスあたりの同時 WebSocket 接続の最大数は、インスタンスタイプ によって異なります

また、エンジンリリース 1.0.3.0 以降、Neptune は接続のアイドルタイムアウトを 1 時間から約 20 分に短縮しました。クライアントが接続を閉じない場合、20 ~ 25 分のアイドルタイムアウト後に接続が自動的に閉じられます。実行コンテキストの有効期間はドキュメント化されませんが、実験では、新しい Neptune AWS Lambda 接続タイムアウトが非アクティブな Lambda 実行コンテキストタイムアウトと適切に一致していることを示しています。非アクティブな実行コンテキストがリサイクルされるまでに、その接続が Neptune によって既に閉じられているか、その後すぐに閉じられる可能性があります。

Amazon Neptune Gremlin AWS Lambda で を使用するための推奨事項

ここでは、関数呼び出しごとに 1 つではなく、Lambda 実行コンテキストのライフタイム全体に 1 つの接続とグラフトラバーサルソースを使用することをお勧めします (すべての関数の呼び出しは 1 つのクライアントリクエストのみを処理します)。同時クライアント要求は、別々の実行コンテキストで実行される異なる関数インスタンスによって処理されるため、関数インスタンス内の同時リクエストを処理するために、接続のプールを維持する必要はありません。使用している Gremlin ドライバに接続プールがある場合は、接続を 1 つだけ使用するように構成します。

接続エラーを処理するには、各クエリで再試行ロジックを使用します。実行コンテキストの存続期間中、単一の接続を維持することが目的ですが、予期しないネットワークイベントによってその接続が突然終了する可能性があります。このような接続障害は、使用しているドライバによって異なるエラーとして現れます。Lambda 関数をコーディングして、これらの接続の問題を処理し、必要に応じて再接続を試みる必要があります。

一部の Gremlin ドライバは再接続を自動的に処理します。たとえば、Java ドライバは、クライアントコードの代わりに Neptune への接続を自動的に再確立しようとします。このドライバでは、関数コードを戻してクエリを再試行するだけで済みます。対照的に、 JavaScript および Python ドライバーは自動再接続ロジックを実装しないため、これらのドライバーでは、関数コードはバックオフ後に再接続を試み、接続が再確立された後にのみクエリを再試行する必要があります。

ここでのコード例には、クライアントがそれを処理していると仮定するのではなく、再接続ロジックが含まれています。

Lambda で Gremlin 書き込みリクエストを使用するための推奨事項

Lambda 関数がグラフデータを変更する場合は、以下の例外を処理する戦略を採用 back-off-and-retryすることを検討してください。

  • ConcurrentModificationException — Neptune トランザクションセマンティクスは、書き込み要求が ConcurrentModificationException で失敗することがあるということを意味しています。このような場合は、エクスポネンシャル back-off-based 再試行メカニズムを試してください。

  • ReadOnlyViolationException — クラスタートポロジは、計画されたイベントまたは計画外のイベントによっていつでも変更される可能性があるため、書き込み責任がクラスタ内のインスタンスから別のインスタンスに移行することがあります。関数コードが、プライマリ (ライター) インスタンスでなくなったインスタンスに書き込みリクエストを送信しようとすると、リクエストは ReadOnlyViolationException で失敗します。この場合、既存の接続を閉じて、クラスターエンドポイントに再接続してから、リクエストを再試行します。

また、書き込みリクエストの問題を処理する back-off-and-retry 戦略を使用する場合は、作成および更新リクエストに対してべき等クエリを実装することを検討してください (例えば、fold().coalesce().unfold() を使用します。

Lambda で Gremlin 読み取りリクエストを使用するための推奨事項

クラスター内に 1 つ以上のリードレプリカがある場合は、これらのレプリカ間で読み取りリクエストのバランスを取ることをお勧めします。1 つのオプションは、リーダーエンドポイントを使うことです。リーダーエンドポイントは、レプリカを追加または削除する、またはレプリカを新しいプライマリインスタンスにするときにクラスタトポロジが変更された場合でも、レプリカ間の接続のバランスをとります。

ただし、リーダーエンドポイントを使用すると、状況によってはクラスタリソースの不均等な使用が発生する可能性があります。リーダーエンドポイントは、DNSエントリが指すホストを定期的に変更することで機能します。DNS エントリが変更される前にクライアントが多数の接続を開くと、すべての接続リクエストが単一の Neptune インスタンスに送信されます。これは、Lambda 関数への多数の同時リクエストによって複数の実行コンテキストが作成され、それぞれが独自の接続を持つ高スループットの Lambda シナリオの場合です。これらの接続がすべてほぼ同時に作成されている場合、接続はすべてクラスタ内の同じレプリカを指し、実行コンテキストがリサイクルされるまでそのレプリカを指し続けます。

インスタンス間でリクエストを分散する方法の 1 つは、リーダーエンドポイントではなく、レプリカインスタンスのエンドポイントのリストからランダムに選択されたインスタンスエンドポイントに接続するように Lambda 関数を設定することです。この方法の欠点は、クラスターを監視し、クラスターのメンバーシップが変更されるたびにエンドポイントリストを更新することで、クラスタートポロジの変更を処理する Lambda コードが必要であることです。

クラスター内のインスタンス間で読み取りリクエストのバランスを取る Java Lambda 関数を作成する場合は、クラスタートポロジを認識しており、Neptune クラスター内のインスタンスのセット間で接続とリクエストを公平に分散する Java Gremlin クライアントである、Amazon Neptune の Gremlin クライアントを使用できます。このブログ投稿には、Amazon Neptune 用の Gremlin クライアントを使用するサンプル Java Lambda 関数が含まれています。

Neptune Gremlin Lambda 関数のコールドスタートを遅らせる可能性がある要因

AWS Lambda 関数が初めて呼び出されたときは、コールドスタートと呼ばれます。コールドスタートのレイテンシーを増加させる要因はいくつかあります。

  • 必ず Lambda 関数に十分なメモリを割り当ててください。  – コールドスタート中のコンパイルは、Lambda 関数の場合よりも大幅に遅くなる可能性があります。EC2これは、 が関数に割り当てるメモリに比例してCPUサイクルを直線的に AWS Lambda 割り当てるためです。 https://docs.aws.amazon.com/lambda/latest/dg/configuration-console.html1,769 MB のメモリにより、関数は 1 つのフル vCPU (1 秒あたり 1 v CPU秒のクレジット) に相当します。適切なCPUサイクルを受け取るのに十分なメモリを割り当てないことの影響は、Java で記述された大規模な Lambda 関数で特に顕著です。

  • IAM データベース認証を有効にすると、コールドスタートが遅くなる可能性があることに注意してください。特に Lambda 関数が新しい署名キーを生成する必要がある場合は、 AWS Identity and Access Management (IAM) データベース認証でもコールドスタートが遅くなる可能性があります。このレイテンシーはコールドスタートにのみ影響し、後続のリクエストには影響しません。IAMDB 認証が接続認証情報を確立すると、Neptune はそれらの認証情報がまだ有効であることを定期的に検証するだけです。