Lambda SnapStart を使用するためのベストプラクティス - AWS Lambda

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

Lambda SnapStart を使用するためのベストプラクティス

ネットワーク接続

Lambda がスナップショットから関数を再開するときは、関数が初期化フェーズ中に確立する接続の状態が保証されません。ほとんどの場合、AWS SDK が確立するネットワーク接続は、自動的に再開されます。これ以外の接続については、以下のベストプラクティスが推奨されます。

ネットワーク接続を再確立する

関数がスナップショットから再開されるときは、常にネットワーク接続を再確立してください。ネットワーク接続を再確立は、関数ハンドラーで実行することをお勧めします。代替手段として、afterRestore ランタイムフックを使用することもできます。

ホスト名を一意の実行環境識別子として使用しない

実行環境をアプリケーション内の一意のノードやコンテナとして特定するために hostname を使用することはお勧めしません。SnapStart では、複数の実行環境の初期状態として単一のスナップショットが使用され、すべての実行環境が InetAddress.getLocalHost() に対して同じ hostname を返します。一意の実行環境アイデンティティ、または hostname 値を必要とするアプリケーションでは、関数ハンドラーで一意の ID を生成することをお勧めします。または、afterRestore ランタイムフックを使用して一意の ID を生成してから、その一意の ID を実行環境の識別子として使用してください。

接続を固定送信元ポートにバインドしない

ネットワーク接続を固定ソースポートにバインドしないことをお勧めします。接続は、関数がスナップショットから再開されるときに再確立され、固定送信元ポートにバインドされたネットワーク接続は失敗する可能性があります。

Java DNS キャッシュを使用しない

Lambda 関数は、既に DNS レスポンスをキャッシュしています。SnapStart で別の DNS キャッシュを使用すると、関数がスナップショットから再開されるときに接続タイムアウトが発生する可能性があります。

java.util.logging.Logger クラスは JVM DNS キャッシュを間接的に有効にできます。デフォルト設定を上書きするには、 を初期化する前に networkaddress.cache.ttl を 0 に設定しますlogger。例:

public class MyHandler { // first set TTL property static{ java.security.Security.setProperty("networkaddress.cache.ttl" , "0"); } // then instantiate logger var logger = org.apache.logging.log4j.LogManager.getLogger(MyHandler.class); }

UnknownHostException 障害を防ぐために、 networkaddress.cache.negative.ttlを 0 に設定することをお勧めします。このプロパティは、 AWS_LAMBDA_JAVA_NETWORKADDRESS_CACHE_NEGATIVE_TTL=0環境変数を使用して Lambda 関数に設定できます。

JVM DNS キャッシュを無効にしても、Lambda のマネージド DNS キャッシュは無効になりません。

パフォーマンスチューニング

注記

SnapStart は、大規模な関数呼び出しで使用すると最も効果的です。頻繁に呼び出されない関数では、パフォーマンスが同じように向上されない場合があります。

SnapStart のメリットを最大限に活用するためにも、起動時のレイテンシーの原因となるクラスは、関数ハンドラーではなく、初期化コードに事前ロードしておくことをお勧めします。そうすることで、高負荷のクラスローディングに関連するレイテンシーが呼び出しパスから排除され、SnapStart での起動パフォーマンスが最適化されます。

初期化中にクラスを事前ロードできない場合は、ダミー呼び出しを使用してクラスを事前ロードすることをお勧めします。これを実行するには、AWS Labs GitHub リポジトリの pet-store 関数からの以下の例にあるように、関数ハンドラーコードを更新します。

private static SpringLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler; static { try { handler = SpringLambdaContainerHandler.getAwsProxyHandler(PetStoreSpringAppConfig.class); // Use the onStartup method of the handler to register the custom filter handler.onStartup(servletContext -> { FilterRegistration.Dynamic registration = servletContext.addFilter("CognitoIdentityFilter", CognitoIdentityFilter.class); registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*"); }); // Send a fake Amazon API Gateway request to the handler to load classes ahead of time ApiGatewayRequestIdentity identity = new ApiGatewayRequestIdentity(); identity.setApiKey("foo"); identity.setAccountId("foo"); identity.setAccessKey("foo"); AwsProxyRequestContext reqCtx = new AwsProxyRequestContext(); reqCtx.setPath("/pets"); reqCtx.setStage("default"); reqCtx.setAuthorizer(null); reqCtx.setIdentity(identity); AwsProxyRequest req = new AwsProxyRequest(); req.setHttpMethod("GET"); req.setPath("/pets"); req.setBody(""); req.setRequestContext(reqCtx); Context ctx = new TestContext(); handler.proxy(req, ctx); } catch (ContainerInitializationException e) { // if we fail here. We re-throw the exception to force another cold start e.printStackTrace(); throw new RuntimeException("Could not initialize Spring framework", e); } }