web.config 設定:
<system.web>
<sessionState mode="InProc | StateServer | SQLServer | Custom"
timeout="20"
cookieless="UseUri | UseCookies | AutoDetect | false"
regenerateExpiredSessionId="true"
...>
</sessionState>
</system.web>
| 模式 | 儲存位置 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|---|
| InProc (預設) | ASP.NET 工作進程記憶體 (w3wp.exe) | 效能最高 (進程內存取)、無序列化開銷、設定最簡單 | 進程回收/重啟/崩潰 → Session 全失;Web Farm 無法共享;大量資料佔用工作進程記憶體觸發回收 | 單伺服器、中小型應用、非關鍵性 Session 資料 |
| StateServer | 獨立 Windows 服務 (aspnet_state.exe),預設 TCP 42424 | 進程外隔離,IIS 回收不影響 Session;支援 Web Farm (共享 StateServer);可運行於專用機器 | 網路呼叫延遲 (序列化/反序列化);單點故障 (StateServer 掛掉全站 Session 失效);需手動啟動服務 | Web Farm、需 Session 持久化、中等流量 |
| SQLServer | SQL Server 資料庫 (預設 tempdb 或自訂資料庫) | 企業級高可用 (叢集/AlwaysOn/鏡像);資料持久化、可查詢稽核;支援大規模 Web Farm | 效能最低 (DB I/O + 序列化);需授權 SQL Server;資料庫維護備份額外成本 | 任務關鍵、大型 Web Farm、法規要求稽核追蹤 |
| Custom | 自訂供應器 (Redis、MongoDB、Memcached、Azure Cache) | 彈性最高、效能可優化、支援分散式架構、現代雲原生首選 | 需自行開發/維護供應器類別;相依第三方基礎設施 | 雲部署、微服務、高併發、需進階功能 (分散式鎖、發布訂閱) |
<sessionState mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
stateNetworkTimeout="30" />
stateConnectionString:tcpip=IP:Port,遠端機器需開放防火牆埠。stateNetworkTimeout:網路逾時秒數,預設 30 秒。services.msc → "ASP.NET State Service" → 啟動類型設為「自動」。HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\AllowRemoteConnection = 1 (預設 0 僅本機)。<sessionState mode="SQLServer"
sqlConnectionString="Data Source=127.0.0.1;Initial Catalog=ASPState;User ID=sa;Password=***;Application Name=MyApp"
allowCustomSqlDatabase="true" />
aspnet_regsql.exe -S . -E -ssadd -sstype p (持久化至自訂資料庫 ASPState) 或 -sstype t (tempdb,重啟遺失)。allowCustomSqlDatabase="true" 允許非預設資料庫名稱。ASPStateTempSessions、ASPStateTempApplications。public class RedisSessionStateProvider : SessionStateStoreProviderBase
{
private ConnectionMultiplexer _redis;
private IDatabase _db;
public override void Initialize(string name, NameValueCollection config)
{
var connStr = config["connectionString"] ?? "localhost:6379";
_redis = ConnectionMultiplexer.Connect(connStr);
_db = _redis.GetDatabase();
base.Initialize(name, config);
}
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
{
return new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), timeout);
}
public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
var key = "session:" + id;
_db.StringSet(key, "", TimeSpan.FromMinutes(timeout));
}
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
{
locked = false; lockAge = TimeSpan.Zero; lockId = null; actions = SessionStateActions.None;
var key = "session:" + id;
var data = _db.StringGet(key);
if (data.IsNullOrEmpty) return null;
// 反序列化 SessionStateItemCollection (略)
return Deserialize(data);
}
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
{
var key = "session:" + id;
var serialized = Serialize(item);
_db.StringSet(key, serialized, TimeSpan.FromMinutes(item.Timeout));
}
// 其他必要覆寫:GetItemExclusive, ReleaseItemExclusive, RemoveItem, ResetItemTimeout, Dispose
}
註冊:
<sessionState mode="Custom" customProvider="RedisSessionProvider">
<providers>
<add name="RedisSessionProvider" type="MyApp.Providers.RedisSessionStateProvider, MyApp" connectionString="redis:6379" />
</providers>
</sessionState>
[Serializable] 的類別) — 但 InProc 不需序列化,故可存放任何物件 (風險:記憶體洩漏、型別安全)。ISerializable 或標記 [Serializable]),預設使用 BinaryFormatter。<sessionState cookieless="UseUri" />
Session ID 嵌入 URL:/。適用於拒絕 Cookie 的舊裝置,**但有安全風險 (Session ID 暴露於 URL、書籤、Referer、Log)**,現代應用**強烈不建議**使用。
| 條件 | 推薦模式 |
|---|---|
| 單伺服器、開發/測試、低流量 | InProc |
| Web Farm (2-10 節點)、需 Session 持久化、無 SQL Server 授權 | StateServer (建議專用機器 + 監控) |
| 企業級 Web Farm、高可用要求、已有 SQL Server 叢集 | SQLServer (持久化模式 -sstype p) |
| 雲原生 (Azure/AWS/GCP)、容器化、微服務、高併發 | Custom (Redis / Azure Cache for Redis / Memcached) |
| 需 Session 資料查詢、稽核、報表 | SQLServer 或 Custom (支援查詢的存儲) |
ASP.NET Session 模式選擇本質是 **效能、可用性、維運成本、架構演進** 的權衡。InProc 最快但最脆弱;StateServer/SQLServer 提供進程外持久化但引入延遲與基礎設施依賴;Custom 供應器 (Redis 為首選) 則是現代分散式系統的標準解法。建議:新專案直接採用 Redis Custom Provider,兼具高效能、高可用、彈性擴展,並避免綁定 IIS/ASP.NET 執行環境。