ASP.NET Core におけるセッション状態の分散保存と構成

ASP.NET Core セッションアーキテクチャの概要

ASP.NET Core アプリケーションにおいて、セッション状態(Session State)の保持には、デフォルトでキャッシュ機構が利用されます。特にマルチサーバー環境や負荷分散を考慮する際、ローカルメモリではなく、分散キャッシュを採用することが推奨されます。ここでは、Redis サーバーをバックエンドストレージとして使用する場合の実装プロセスについて解説します。

Redis 接続サービスの登録

Redis を利用するためには、適切な NuGet パッケージへの依存関係が必要です。具体的には、`Microsoft.Extensions.Caching.StackExchangeRedis` などのパッケージをインストールし、DI コンテナ(Dependency Injection Container)に登録することで機能します。

アプリケーションのホストビルダー設定段階において、`IServiceCollection` に分散 Redis キャッシュの実装を追加します。その後、セッション機能を有効にするためのサービスも登録します。

// Program.cs の現代的手法による記述例
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System.Text.Json;

var builder = WebApplication.CreateBuilder(args);

// 1. 分散キャッシュとしての Redis サービス登録
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "192.168.0.190"; // Redis サーバーアドレス
    options.InstanceName = "UserSession_";   // キー名のプレフィックス
});

// 2. セッション機能の有効化
builder.Services.AddSession(session =>
{
    session.IdleTimeout = TimeSpan.FromMinutes(30);
    session.Cookie.HttpOnly = true;
});

var app = builder.Build();

// 3. ミドルウェアのパイプライン配置
app.UseSession();

// リクエスト処理
app.Map("/", async (HttpContext context) =>
{
    await context.Session.LoadAsync();

    var userId = context.Session.GetString("user_id");
    
    if (string.IsNullOrWhiteSpace(userId))
    {
        userId = Guid.NewGuid().ToString("N")[..8];
        context.Session.SetString("user_id", userId);
        context.Response.ContentType = "text/plain; charset=utf-8";
        await context.Response.WriteAsync($"新規セッション発行:{userId}");
    }
    else
    {
        context.Response.ContentType = "text/plain; charset=utf-8";
        await context.Response.WriteAsync($"既存ユーザーID: {userId}");
    }
});

app.Run();

セッションデータの永続化と期間設定

セッションデータが生成されると、キーと値を含む辞書データは、定義されたシリアライズフォーマットに従ってバイト配列に変換され、分散ストアに保存されます。

デフォルトでは、スライディング expiration(スライドタイムアウト)戦略が採用されています。これは、クライアントがセッションへアクセスするたびに有効期限のリセットが行われることを意味します。初期設定の無効時間(Idle Timeout)は通常 20 分ですが、これはカスタマイズ可能です。

データ型操作の実装原理

フレームワーク内部では、単純な文字列や数値型のデータをセッションに格納するために、拡張メソッドが用意されています。例えば、整数(int)の場合は 4 バイトの配列に変換して保持され、文字列(string)の場合は UTF-8 エンコードされたバイト列として処理されます。

// カスタムヘルパーメソッドによる抽象化例
public static class SessionHelper
{
    public static void SaveCounter(this ISession session, int value)
    {
        var buffer = new byte[sizeof(int)];
        Buffer.BlockCopy(new[] { value }, 0, buffer, 0, sizeof(int));
        session.Set("counter_key", buffer);
    }

    public static int? LoadCounter(this ISession session)
    {
        var data = session.Get("counter_key");
        if (data == null || data.Length != sizeof(int)) return null;
        
        return BitConverter.ToInt32(data, 0);
    }
}

このように、基盤となる `ISession` インターフェースはバイナリデータのみの取り扱いですが、ユーザビリティ向上のために型変換を担う拡張メソッド群が存在します。

セッションオプションの詳細設定

セッションの動作を制御する SessionOptions クラスにより、Cookie の挙動や I/O タイムアウトなどを指定できます。

  • Cookie: システムが生成する Cookie の設定を制御します。名前、パス、セキュリティポリシーなどを指定可能です。
  • IdleTimeout: ユーザーの活動がない場合にセッションが失われるまでの待機時間を定義します。
  • IOTimeout: セッションストアとの読み書き操作にかかる最大許容時間を設定します。非同期処理において重要となります。

これらの設定を適切に調整することで、セキュリティ強化やパフォーマンス最適化が可能になります。

タグ: ASP.NET Core redis Session DistributedCaching Middleware

6月5日 22:49 投稿