Goで書いたLambdaでインメモリキャッシュできるか確認してみた

2022.04.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部のhagiwaraです。

Lambdaでインメモリキャッシュを使いたかったのですが、カスタムランタイムをつかってGoで書いたLambdaで使えるか自信がなかったので、試してみました。

結論から言うと、JavaScriptランタイム等と同様に使うことができました。

やってみる

環境

  • go 1.18.0
  • node 17.9.0

実装

グローバルスコープに cachedReqId を定義し、空文字列の場合はリクエストIDを代入します。
この値と呼び出したリクエストIDが異なれば、キャッシュが効いていることになります。

package main

import (
    "context"
    "errors"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-lambda-go/lambdacontext"
    "log"
)

type MyEvent struct {
    Name string `json:"name"`
}

// グローバルスコープに文字列を定義
var cachedReqId = ""

func HandleRequest(ctx context.Context, name MyEvent) (string, error) {
    var reqId string
    if lc, ok := lambdacontext.FromContext(ctx); ok {
        reqId = lc.AwsRequestID
    } else {
        return "ERROR", errors.New("lambda context cast error")
    }

    // 空の場合のみリクエストIDを代入
    if cachedReqId == "" {
        cachedReqId = reqId
    }

    log.Printf("ReqId: %s, cachedReqId: %s", reqId, cachedReqId)

    return "SUCCESS", nil
}

func main() {
    lambda.Start(HandleRequest)
}

デプロイ

CDK(TypeScript)を使ってAL2のカスタムランタイム上で動作するLambdaをデプロイしました。
(手軽に作りたかったので、experimentalなモジュール@aws-cdk/aws-lambda-go-alphaを使っています)

#!/usr/bin/env node
import 'source-map-support/register'
import { Construct } from 'constructs'
import { App, Stack, StackProps } from 'aws-cdk-lib'
import { GoFunction } from '@aws-cdk/aws-lambda-go-alpha'

const app = new App()

class LambdaStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props)

    new GoFunction(this, 'handler', {
      entry: '../lambda'
    })
  }
}

new LambdaStack(app, 'LambdaStack')

結果

一定時間はインメモリキャッシュが効いてることが確認できました。
試した環境では、3分程度は効いていおり、呼び出しを5分程度開けると、コールドスタートになり再設定されているようでした。

lambda 実行ログ

まとめ

AL2を使ったカスタムランタイムで、Goでインメモリキャッシュが使えることが確認できました。

未検証ですが、issueによると、Rustでもできそうな感じです。