0
0

momentoを利用してサーバレスキャッシングしてみた

Posted at

はじめに

最近インメモリキャッシュサービスを格安で利用することができないかと色々調べていました。
(Elasticacheなどのサービスは高いのでなるべく無料のものを利用したい。)

その結果、Momentoというサービスを発見しましたので、今回はそれについて触ってみてLambdaへの実装までを実施しました。

Momentoとは ?

インメモリキャッシュのSaaSサービスです。正確にはMomento Cacheにてインメモリキャッシュを行うことができます。
AWS上でキャッシュを利用するとなると、ElastiCacheやAppSync(正確にはElasticache)などを利用す

毎月5GBまでのデータの登録は無料で利用することができるため、。
その後は1GBあたり0.50ドル課金されます。
スタンダードプラン以降はCloudWatch メトリクスへエクスポートすることも可能になります。

Momento設定内容

今回はMomento cache を作成して

キャッシュを作成するにはMomento Cache画面にて「キャッシュを作成」をクリックします。

image.png

以下のようにキャッシュ名とクラウドプロバイダー、リージョンを選択すればこれで完了です。
かなり簡単に作成することができました。
image.png

あとは、キャッシュを利用するための APIキーの発行です。API コンソールを作成して
image.pngからプロバイダーと権限を作成します。

以上で、momentoでの設定は完了になります。
超シンプルにキャッシュを作成することができました。

AWS Lambda + Momento でサーバレスキャッシングやってみた

次にAWS Lambda から Momento Cacheへ接続してみたいと思います。

複数の関数でmomentoパッケージを利用したいので今回はmomentoパッケージをLayer化して、
Lambda関数で利用したいと思います。

今回使用するLambdaランタイム環境はPython3.10とします。

  • AWS CDK

1. Lambda Layer Package

PypiからMomento Python Client Libraryをインストールします。

以前投稿したように「invalid ELF header」によるELF headerの不一致によるエラーが発生するので、Lambdaの公式ランタイムのイメージ上でmomentoをインストールするようにします。

具体的な手順はこちらを参考にお願いします。

2. Lambda デプロイ

今回はCDKを使用してLambdaとLambdaLayerを作成してデプロイしようと思います。使用言語はTypeScriptで記述していこうと思います。

CDKの使い方についてはこちらを参考に。

CDKアプリケーションのエントリポイントは以下の通りです。./lib下のCDKアプリケーションのメインスタックを呼び出します。今回はLambdaとLambdaLayerのスタックを作成します。

./bin/demo-momento.ts
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { LambdaFuncStack } from '../lib/lambda-func.ts';
import { LambdaLayerStack } from '../lib/lambda-layer.ts';


const app = new cdk.App();

new LambdaLayerStack(app, 'LambdaLayerStack', {});
new LambdaFuncStack(app, 'LambdaFuncStack', {});

Lambda Layerを作成するCDKアプリケーションを作成します。
./lib下にて
layer.zipの部分は、「1. Lambda Package」で作成したmomentoのパッケージファイルの相対pathを指定します。

./lib/lambda-layer.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';

import * as path from 'path';


export class LambdaLayerStack extends cdk.Stack {
    public readonly layer: lambda.LayerVersion;
    constructor(scope: Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        const commonLayerName = `demo-layer-momento`;
        const commonLayer = new lambda.LayerVersion(this, commonLayerName, {
            layerVersionName: commonLayerName,
            code: lambda.AssetCode.fromAsset(path.join(__dirname, '../src/lambda/layers/layer.zip')), // momento パッケージを圧縮したファイルを指定
            compatibleRuntimes: [lambda.Runtime.PYTHON_3_10],

        });

        // rtn
        this.layer = commonLayer;

    }
}

続いてLambdaFunctionを作成するCDKになります。

./lib/lambda-func.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as iam from 'aws-cdk-lib/aws-iam';

import * as path from 'path';

export class LambdaFuncStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        const region = this.region;
        const accountId = this.account;

        const funcName = 'demo-func-hello-world';
        const layerArn = `arn:aws:lambda:${region}:${accountId}:layer:demo-layer-momento:1`;

        const momentoCacheName = 'test-api-cache'

        const func = new lambda.Function(this, funcName, {
            functionName: funcName,
            runtime: lambda.Runtime.PYTHON_3_10,
            code: lambda.Code.fromAsset(path.join(__dirname, '../src/lambda/hello_world')),
            handler: 'lambda_function.lambda_handler',
            environment: {
                MOMENTO_API_KEY: 'xXxXxX',
                MOMENTO_CACHE_NAME: momentoCacheName,
                APISPORTS_API_KEY: 'xXxXxX'
            },
            timeout: cdk.Duration.seconds(120),
        });

        func.addLayers(lambda.LayerVersion.fromLayerVersionArn(this, `LambdaLayer`, layerArn));

    }
}

次にLambdaのソースファイルとなるlambda_function.pyを作成したいと思います。
今回はシンプルにMomentoクライアント認証したのち、キャッシュにキーと値をMomento Cacheへセットするだけのシンプルなものになります。

./src/lambda/hello_world/lambda_function.py
import json
import os
from datetime import timedelta
import boto3 
import logging
from momento import CacheClient, Configurations, CredentialProvider
from momento.responses import CacheGet, CacheSet, CreateCache, ListCaches, CacheIncrement

MOMENTO_API_KEY = os.getenv('MOMENTO_API_KEY', 'xXxXxXxXxXxXxXxXxX')
MOMENTO_CACHE_NAME = os.getenv('MOMENTO_CACHE_NAME', 'test-cache-name')


logger = logging.getLogger()
logger.setLevel("INFO")

def lambda_handler(event, context):
    client = create_cache_client()
    client.set(MOMENTO_CACHE_NAME, "test-key", "test-value")
    res = client.get(MOMENTO_CACHE_NAME, "test-key")
    logger.info("Result: {}".format(res))
    return {
        'statusCode': 200,
        'body': json.dumps(res)
    }


def create_cache_client():
    cache_client = CacheClient(
        configuration=Configurations.Laptop.v1(),
        credential_provider=CredentialProvider.from_environment_variable("MOMENTO_API_KEY"),
        default_ttl=timedelta(seconds=600),
    )
    return cache_client

最後にデプロイコマンドを実行します。
以下のコマンドを実行して、CDKデプロイを実施します。

cdk synth

cdk deploy

最後にLambdaのテストをします。
以下のようにキャッシュのキーに関連した値を取得することができます。
image.png

終わりに

今回は、Momentoと呼ばれるSaaSのサービスについて触ってみました。
ほかにも有用なSaaSサービスがあったらそれにも触ってみたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0