Amazon DynamoDB を ASP.NET Core の分散キャッシュストレージとして使用できる AWS .NET Distributed Cache Provider for DynamoDB を使ってみた

2023.07.31

いわさです。

先日 AWS より AWS .NET Distributed Cache Provider というライブラリが使えるようになったというアナウンスがありました。

ASP.NET Core ではミドルウェアを DI する仕組みが備わっており、規定のインターフェースが実装された様々なミドルウェアを簡単に導入することが可能です。
今回リリースされたライブラリはその中の分散キャッシュプロバイダである IDistributedCache が実装されており、分散アプリケーションで DynamoDB を共通のセッションストアやキャッシュストアとして簡単に利用できるようにするためのものです。

実際に試しに使ったところ、非常に簡単に DynamoDB と連携することが出来ましたので紹介します。

検証用の ASP.NET Core アプリを作成

まずは適当な ASP.NET Core アプリケーションを用意します。

% dotnet new web
The template "ASP.NET Core Empty" was created successfully.

Processing post-creation actions...
Restoring /Users/iwasa.takahito/work/hoge0731dotnet/hoge0731dotnet.csproj:
  Determining projects to restore...
  Restored /Users/iwasa.takahito/work/hoge0731dotnet/hoge0731dotnet.csproj (in 34 ms).
Restore succeeded.

クエリ文字列とリクエスト日時を返却する動的なメソッドを作成します。

Program.cs

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.MapGet("/{hoge}", (string hoge) => 
{
    var value = DateTime.Now.ToString();
    return $"{hoge}: {value}";
});

app.Run();

この時点では次のようにリクエスト内容とタイミングに応じて異なるレスポンスが取得されるようになっています。

% curl http://localhost:5035/111
111: 7/31/2023 8:21:59 PM
% curl http://localhost:5035/222
222: 7/31/2023 8:22:02 PM

AWS .NET Distributed Cache Provider を導入

AWS .NET Distributed Cache Provider をプロジェクトにインストールします。
いつものように NuGet パッケージマネージャを使います。

% dotnet add package AWS.AspNetCore.DistributedCacheProvider --version 0.9.2
  Determining projects to restore...
  Writing /var/folders/4d/nhd1bp3d161crsn900wjrprm0000gp/T/tmpHJfrsF.tmp
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/local/share/dotnet/sdk/7.0.203/trustedroots/codesignctl.pem'.
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/local/share/dotnet/sdk/7.0.203/trustedroots/timestampctl.pem'.
info : Adding PackageReference for package 'AWS.AspNetCore.DistributedCacheProvider' into project 

:

info : Generating MSBuild file /Users/iwasa.takahito/work/hoge0731dotnet/obj/hoge0731dotnet.csproj.nuget.g.props.
info : Writing assets file to disk. Path: /Users/iwasa.takahito/work/hoge0731dotnet/obj/project.assets.json
log  : Restored /Users/iwasa.takahito/work/hoge0731dotnet/hoge0731dotnet.csproj (in 4.49 sec).

AddAWSDynamoDBDistributedCacheメソッドのオプションで対象のテーブルやパーティションキーなどを設定します。
以下は最低限の構成ですが、TTL などももちろん設定可能です。

Program.cs

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAWSDynamoDBDistributedCache(options =>
{
    options.TableName = "hoge0731cache";
    options.PartitionKeyName = "hoge";
});

:

データストアになる DynamoDB も用意しておきましょう。

アプリケーション上でキャッシュを使用する

以下ではハイライト部分でキャッシュの取得と保存をそれぞれ行っています。
実装上文字列をバイト配列に変換しています。

Program.cs

using System.Text;
using Microsoft.Extensions.Caching.Distributed;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAWSDynamoDBDistributedCache(options =>
{
    options.TableName = "hoge0731cache";
    options.PartitionKeyName = "hoge";
});

var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.MapGet("/{hoge}", async (IDistributedCache distributedCache, string hoge) => 
{
    var cache = await distributedCache.GetAsync(hoge);
    string value = string.Empty;
    if(cache == null)
    {
        value = DateTime.Now.ToString();
        await distributedCache.SetAsync(hoge, Encoding.ASCII.GetBytes(value));
    }
    else
    {
        value = Encoding.ASCII.GetString(cache);
    }
    return $"{hoge}: {value}";
});

app.Run();

実行し、リクエストを送信してみると...

% curl http://localhost:5035/111
111: 7/31/2023 8:37:04 PM
% curl http://localhost:5035/222
222: 7/31/2023 8:37:09 PM
% curl http://localhost:5035/111
111: 7/31/2023 8:37:04 PM

おお、キャッシュされた値が使われていますね!!

AWS マネジメントコンソールからも DynamoDB テーブルを確認してみると、次のようにアイテムが登録されていました。

今回はローカル実行で、権限が付与されたデフォルトプロファイルが使用されていますが、実際には環境ごとに IAM ポリシーの設定が必要です。
詳細は以下をご確認ください。

さいごに

本日は Amazon DynamoDB を ASP.NET Core の分散キャッシュストレージとして使用できる AWS .NET Distributed Cache Provider for DynamoDB を使ってみました。

分散キャッシュといえば ElastiCache を検討することが多いと思いますが、サーバーレスなセッションストアを採用したいシーンもたまにあります。
そういったシーンでは役に立つのではないでしょうか。
また、IDistributedCache が実装されているので、アプリケーションコードに適用しやすく非常に使いやすいですね。