首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WCF 雙向通訊實戰:Session 管理完整實作 (下)

     編輯:關於.NET

SessionManager 核心邏輯深度解析

承接上篇,我們將業務邏輯集中於靜態類別 SessionManager,採用雙字典架構:

  • CurrentSessionList:Guid -> SessionInfo,追蹤所有活躍 Session。
  • CurrentCallbackList:Guid -> ISessionCallback,維護對應的 Client 回呼通道。

靜態建構函式從設定檔讀取 SessionTimeout(分鐘),初始化兩個字典與同步鎖 _syncHelper。

Session 啟動與結束

public static Guid StartSession(SessionClientInfo clientInfo)
{
    Guid sessionID = Guid.NewGuid();
    ISessionCallback callback = OperationContext.Current.GetCallbackChannel<ISessionCallback>();
    var sesionInfo = new SessionInfo
    {
        SessionID = sessionID,
        StartTime = DateTime.Now,
        LastActivityTime = DateTime.Now,
        ClientInfo = clientInfo
    };
    lock (_syncHelper)
    {
        CurrentSessionList.Add(sessionID, sesionInfo);
        CurrentCallbackList.Add(sessionID, callback);
    }
    return sessionID;
}

public static void EndSession(Guid sessionID)
{
    if (!CurrentSessionList.ContainsKey(sessionID)) return;
    lock (_syncHelper)
    {
        CurrentCallbackList.Remove(sessionID);
        CurrentSessionList.Remove(sessionID);
    }
}

強制終止 Session (KillSessions)

管理員可強制終止指定 Session,流程:移除 SessionInfo -> 透過 Callback 通知 Client (OnSessionKilled) -> 移除 Callback。因回呼為 One-Way 非同步,鎖持有時間極短,對並發影響微乎其微。

核心難點:Timeout 輪詢與 Renew 機制

採用 服務端主動輪詢 + 非同步並行 + Callback 協商 設計:

  1. 定時器每 5 秒呼叫 RenewSessions()。
  2. 遍歷 CurrentSessionList,若 Now - LastActivityTime < Timeout 則略過。
  3. 否則透過 BeginInvoke 非同步呼叫 Client 端 Renew(),並收集 WaitHandle。
  4. WaitHandle.WaitAll 等待所有非同步作業完成,最後呼叫 ClearSessions() 清理逾時/已終止項目。
[MethodImpl(MethodImplOptions.Synchronized)]
public static void RenewSessions()
{
    var waitHandleList = new List<WaitHandle>();
    foreach (var session in CurrentSessionList)
    {
        RenewSession renewsession = delegate(KeyValuePair<Guid, SessionInfo> sessionInfo)
        {
            if (DateTime.Now - sessionInfo.Value.LastActivityTime < Timeout) return;
            try
            {
                TimeSpan renewDuration = CurrentCallbackList[sessionInfo.Key].Renew();
                if (renewDuration.TotalSeconds > 0)
                    sessionInfo.Value.LastActivityTime += renewDuration;
                else
                {
                    sessionInfo.Value.IsTimeout = true;
                    CurrentCallbackList[sessionInfo.Key].OnSessionTimeout(sessionInfo.Value);
                }
            }
            catch (CommunicationObjectAbortedException)
            {
                sessionInfo.Value.IsTimeout = true;
            }
        };
        IAsyncResult result = renewsession.BeginInvoke(session, null, null);
        waitHandleList.Add(result.AsyncWaitHandle);
    }
    if (waitHandleList.Count == 0) return;
    WaitHandle.WaitAll(waitHandleList.ToArray());
    ClearSessions();
}

三大關鍵設計考量

  1. 非同步並行:避免同步逐一檢查導致延遲,尤其在高併發下。
  2. 例外處理:捕捉 CommunicationObjectAbortedException 視為 Client 已斷線,直接標記逾時。
  3. 延遲清理:待所有非同步作業完成 (WaitAll) 後再統一清理字典,避免並發修改集合引發異常。

Service 與 Hosting 實作

SessionManagementService 僅薄封裝 SessionManager,設定 InstanceContextMode.Single 與 ConcurrencyMode.Multiple 支援高併發。Hosting 端啟動 ServiceHost 並建立 Timer 每 5 秒觸發 RenewSessions()。

Client 端實作 (WinForm)

SessionUtility 封裝 DuplexChannelFactory 與 Channel 生命週期。重點在 SessionCallback 實作:

public class SessionCallback : ISessionCallback
{
    public TimeSpan Renew()
    {
        return SessionUtility.Timeout - (DateTime.Now - SessionUtility.LastActivityTime);
    }
    public void OnSessionKilled(SessionInfo info)
    {
        MessageBox.Show("Session 已被強制終止!", info.SessionID.ToString());
        Application.Exit();
    }
    public void OnSessionTimeout(SessionInfo info)
    {
        MessageBox.Show("Session 逾時!", info.SessionID.ToString());
        Application.Exit();
    }
}

Renew() 根據「上次滑鼠移動時間」動態計算剩餘可延長時間。Form 載入時遞迴註冊所有控制項的 MouseHover 事件更新 LastActivityTime,完美模擬使用者活躍度。

執行畫面驗證

  • Client 啟動 30 秒無操作 -> 彈出逾時視窗並自動關閉。
  • 多 Client 並行 -> 管理員介面列出所有活躍 Session (IP、UserName、時間)。
  • 管理員 Kill 目標 Session -> 目標 Client 立即收到通知並退出。

總結

此架構展示 WCF 雙向通訊在分散式 Session 管理的強大威力:服務端掌握主動權,透過非同步輪詢與 Callback 協商實現即時、可擴展的 Session 生命週期控制,完美解決傳統 Client 輪詢模式的即時性與效能難題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved