-
Notifications
You must be signed in to change notification settings - Fork 0
MS_ASPNETCoreDistributedCache
昔で言う、StateServer や SQL Serverのモード。
補足(対応関係): ASP.NET Session の
セッション状態モードとの対応を整理しておく。
ASP.NET のモード ASP.NET Core の対応 登録メソッド InProc メモリ内(既定) AddDistributedMemoryCache()StateServer Redis 等 AddStackExchangeRedisCache()SQLServer SQL Server AddDistributedSqlServerCache()Custom 任意の IDistributedCache実装自作 重要な違いは、ASP.NET Core では
IDistributedCacheという 1 つの抽象に統一されている点である。【ASP.NET】 セッション専用のプロバイダー機構 【ASP.NET Core】 IDistributedCache(汎用キャッシュの抽象) └─ その利用者の 1 つとして Session があるこのため、セッション以外の用途(アプリ キャッシュ)にも同じ物を使える。
抽象 範囲 用途 IMemoryCache1 プロセス内 高速。マスタ データ等 IDistributedCache複数台で共有 セッション、共有キャッシュ HybridCache(.NET 9)両方を 2 段で L1(メモリ)+ L2(分散)
AddDistributedMemoryCache()は「分散」という名前だが
プロセス内メモリである点に注意する
(インターフェイスを揃えるための実装で、複数台では共有されない)。
Redis が一般的
.NET Core 2.1 以前のバージョンでは、AddDistributedRedisCache を、
.NET Core 2.2 以降のバージョンでは、AddStackExchangeRedisCache を使う。
-
NuGet
- StackExchange.Redis
- Microsoft.Extensions.Caching.StackExchangeRedis
- Microsoft.AspNetCore.DataProtection.StackExchangeRedis
-
コード
using StackExchange.Redis;
using Microsoft.AspNetCore.DataProtection;
...
var redis = ConnectionMultiplexer
.Connect(Environment.GetEnvironmentVariable("REDIS"));
services
.AddDataProtection()
.PersistKeysToStackExchangeRedis(redis, "DataProtectionKeys");
services.AddStackExchangeRedisCache(option =>
{
option.Configuration = Environment
.GetEnvironmentVariable("REDIS");
option.InstanceName = "RedisInstance";
});補足(このサンプルの要点): 短いコードだが、
複数台構成に必要な 2 つが両方入っている点が重要である。① PersistKeysToStackExchangeRedis … データ保護キーの共有 → Cookie を全台で復号できるようにする ② AddStackExchangeRedisCache … セッション データの共有 → セッションの中身を全台で読めるようにする①を忘れると、②だけ入れても動かない
(ASP.NET Coreのデータ保護)。
原文がこの 2 つを 1 つのサンプルにまとめているのは的確である。
SetApplicationNameも必要なので、実運用では次の形になる。var builder = WebApplication.CreateBuilder(args); var redisConn = builder.Configuration.GetConnectionString("Redis"); var redis = await ConnectionMultiplexer.ConnectAsync(redisConn); // ① データ保護キーを共有 builder.Services.AddDataProtection() .SetApplicationName("MyApp") // ← 全台で同じ .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys"); // ② 分散キャッシュ builder.Services.AddStackExchangeRedisCache(o => { o.Configuration = redisConn; o.InstanceName = "MyApp:"; // キーの前置き }); // ③ セッション(②を保存先として使う) builder.Services.AddSession(o => { o.IdleTimeout = TimeSpan.FromMinutes(30); o.Cookie.IsEssential = true; });
AddDistributedRedisCacheは廃止済みである
(Microsoft.Extensions.Caching.Redisパッケージごと非推奨)。
原文が述べる通りAddStackExchangeRedisCacheを使う。
Connect メソッドの引数は config で、ココに、以下のように、
「,」区切りで、色々なオプションを設定可能であるもよう。
ConnectionMultiplexer connection =
ConnectionMultiplexer.Connect("endpoint,password=password,ConnectTimeout=10000");- 参考
- Configuration | StackExchange.Redis
https://stackexchange.github.io/StackExchange.Redis/Configuration.html#configuration-options
- Configuration | StackExchange.Redis
補足(実務で指定することが多いオプション):
オプション 用途 ssl=trueマネージド Redis はほぼ必須(Azure Cache for Redis 等) abortConnect=false起動時に Redis が未起動でも落とさない(後で再接続) connectTimeout/syncTimeoutタイムアウト(既定 5000ms) connectRetry接続リトライ回数 defaultDatabase使用する DB 番号 myredis.redis.cache.windows.net:6380,password=xxx,ssl=True,abortConnect=False
abortConnect=falseはコンテナ環境でほぼ必須である
(アプリと Redis の起動順が保証されないため)。なお、接続文字列にパスワードを直書きしないこと。
.NET Core config の構成プロバイダー
(環境変数、ユーザー シークレット、Key Vault)から読み込む。// ConnectionMultiplexer は「1 アプリに 1 つ」を共有する(Singleton) builder.Services.AddSingleton<IConnectionMultiplexer>( _ => ConnectionMultiplexer.Connect(redisConn));
ConnectionMultiplexerを毎回newしないのが定石である
(内部で接続を多重化するため、使い回すことが前提の設計)。
-
昔で言う、machine.config の machineKey の話。
-
前述のサンプル・コードのように、
- AddDataProtection()
- SetApplicationName()
- PersistKeysToStackExchangeRedis()
を呼び出す。
補足(切り分けの手順): 「複数台にしたらログインが外れる/
セッションが消える」という症状の切り分け順。① 1 台に固定(スティッキー セッション)すると直るか? 直る → 共有できていない。②へ ② Redis にセッションのキーが入っているか? redis-cli KEYS "MyApp:*" 入っていない → 分散キャッシュの設定漏れ ③ データ保護キーは共有されているか? redis-cli GET "DataProtection-Keys" 無い → PersistKeysTo* の設定漏れ ④ ApplicationName は全台同じか? 違う → 鍵束を共有していても別アプリ扱いになる ⑤ ログに CryptographicException / 「キーが見つかりません」が出ていないか③④ が原因であることが圧倒的に多い。
- ASP.NET Core での分散キャッシュ
https://learn.microsoft.com/ja-jp/aspnet/core/performance/caching/distributed - ASP.NET Core での HybridCache ライブラリ
https://learn.microsoft.com/ja-jp/aspnet/core/performance/caching/hybrid - ASP.NET Core でのメモリ内キャッシュ
https://learn.microsoft.com/ja-jp/aspnet/core/performance/caching/memory
- ASP.NET Core Distributed Session with Redis | by Luiz Adolphs
https://medium.com/@LuizAdolphs/asp-net-core-distributed-session-with-redis-8ce8bacf26cd - How to distribute Data Protection keys with an ASP.NET Core web app | by Tiago Araújo | The Startup | Jun, 2020
https://medium.com/swlh/how-to-distribute-data-protection-keys-with-an-asp-net-core-web-app-8b2b5d52851b
- ASP.NET Core on Linux で Session Replication するにはNFSが必要そうだというお話
http://tech.tanaka733.net/entry/aspnet-core-in-linux-sessoin-replocation - ASP.NET Core で複数Webサーバーでセッションを共有するときは、
IDistributedCacheとIDataProtectionに注意しないといけない話
http://tech.tanaka733.net/entry/session-sharing-in-aspnetcore
Tags: 移行, .NET開発, .NET Core, ASP.NET, ASP.NET MVC
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。