JavaScript クロージャーを活用したインメモリキャッシュによる AWS Lambda の最適化

JavaScript クロージャーを活用したインメモリキャッシュによる AWS Lambda の最適化

岩佐 孝浩
岩佐 孝浩
4 min read
Lambda In-memory Caches Closures in JavaScript

AWS Lambda ユーザーは、インメモリキャッシュを活用して、パフォーマンス向上とコスト削減が可能です。

例えば、 Secrets Manager に保管されたシークレット値は、最新の値が必要ない限り、 handler 外部でキャッシュできます。これは、 Static Initialization と呼ばれています。

この投稿では、クロージャーを使用したインメモリキャッシュを活用して、 AWS Lambda 関数を最適化する方法を紹介します。

非最適化 Lambda 関数

最初に、下記のコードをご覧ください。

重要なポイントは、次のとおりです。

  • 呼び出しごとに SecretsManagerClient のインスタンスを生成します。
  • 呼び出しごとに Secrets Manager からシークレット値を取得します。
import {
  SecretsManagerClient,
  GetSecretValueCommand,
} from '@aws-sdk/client-secrets-manager';

export async function handler(event) {
  const client = new SecretsManagerClient();
  const command = new GetSecretValueCommand({ SecretId: '<YOUR_SECRET_ID>' });
  const { SecretString } = await client.send(command);

  return {
    statusCode: 200,
    body: SecretString,
  };
}

関数を数回実行すると、次のようなレスポンスが得られます。この例では、 Duration は 153.66 ミリ秒です。

Test Event Name
TestEvent

Response
{
  "statusCode": 200,
  "body": "{\"message\":\"Hello World\"}"
}

Function Logs
START RequestId: 55f3596f-b4c1-4fcd-bc34-2c63674bd3cd Version: $LATEST
END RequestId: 55f3596f-b4c1-4fcd-bc34-2c63674bd3cd
REPORT RequestId: 55f3596f-b4c1-4fcd-bc34-2c63674bd3cd	Duration: 153.66 ms	Billed Duration: 154 ms	Memory Size: 128 MB	Max Memory Used: 89 MB

Request ID
55f3596f-b4c1-4fcd-bc34-2c63674bd3cd

最適化 Lambda 関数

次に、下記のコードをご覧ください。

重要なポイントは、次のとおりです。

  • シークレット値を取得する関数は、 useGetSecret 内のクロージャーとして定義されています。 この関数名は、 React Hooks を参考にしてみました。
  • シークレット値は初回の呼び出しでキャッシュされ、 Lambda ランタイムが終了するまで、常にキャッシュされた値を返却します。
  • getSecret を呼び出す側では、キャッシュを意識する必要がなく、関心の分離につながります。
import {
  SecretsManagerClient,
  GetSecretValueCommand,
} from '@aws-sdk/client-secrets-manager';

const getSecret = useGetSecret('<YOUR_SECRET_ID>');

export const handler = async (event) => {
  const secret = await getSecret();
  return {
    statusCode: 200,
    body: secret,
  };
};

function useGetSecret(id) {
  const client = new SecretsManagerClient();
  const command = new GetSecretValueCommand({ SecretId: id });
  let secret = '';

  return async () => {
    if (secret) {
      return secret;
    }
    const { SecretString } = await client.send(command);
    secret = SecretString;
    return secret;
  };
}

関数を数回実行すると、次のようなレスポンスが得られます。この例では、 Duration は 1.28 ミリ秒です。

キャッシュによって、関数のパフォーマンスが劇的に向上していることが分かります。

Test Event Name
TestEvent

Response
{
  "statusCode": 200,
  "body": "{\"message\":\"Hello World\"}"
}

Function Logs
START RequestId: aaba6d16-19ee-437a-9592-f708b3ed7c8b Version: $LATEST
END RequestId: aaba6d16-19ee-437a-9592-f708b3ed7c8b
REPORT RequestId: aaba6d16-19ee-437a-9592-f708b3ed7c8b	Duration: 1.28 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 88 MB

Request ID
aaba6d16-19ee-437a-9592-f708b3ed7c8b

まとめ

AWS Lambda ユーザーは、インメモリキャッシュを積極的に活用することで、パフォーマンスを向上させ、コストを削減できます。

この投稿が、お役に立てば幸いです。

岩佐 孝浩

岩佐 孝浩

Software Developer at KAKEHASHI Inc.
AWS を活用したクラウドネイティブ・アプリケーションの要件定義・設計・開発に従事。 株式会社カケハシで、処方箋データ収集の新たな基盤の構築に携わっています。 Japan AWS Top Engineers 2020-2023