分佈式之Session共享

在上一篇博文中我們通過Nginx+IIS實現了一個簡單的負載均衡,那麼隨之而來的問題就是多個站點在切換時如何共享Session信息,本篇介紹在.net中通過Redis實現分佈式站點的Session共享,並且無需修改原項目的Session讀取方式。

ASP.Net session存儲方式

首先我們看下asp.net中session能採用的存儲方式及優缺點。如下:

  1. InProc模式(進程內模式) ,爲默認設置。優點是性能高無需跨進程讀取,缺點是依賴asp.net進程,當進程崩潰重啓時會丟失,並且在分佈式的情況下無法多個站點共享。
  2. StateServer模式(狀態服務器模式)。會話狀態存儲在一個名爲ASP.Net狀態服務的單獨進程中,這確保了在重新啓動Web應用程序時會保留會話狀態,並讓會話狀態可用於網絡中的多個Web服務器。
  3. SQL Server模式。會話狀態存儲到一個SQL Server數據庫中。這確保了在重新啓動Web應用程序時會保留會話狀態,並讓會話狀態可用於網絡中的多個Web服務器。
  4. Custom模式。此模式允許您指定自定義存儲提供程序,例如分佈式中常採用自定義模式將站點Session存儲在Redis或Memcached中。
    本篇即採用Custom模式自定義存儲提供程序將Session存儲在Redis中。

Redis存儲Session

採用Custom模塊需要修改web.config配置文件中網站的sessionState節點的mode屬性爲Custom,另外我們需要寫一個類實現SessionStateStoreProviderBase抽象類,通過實現抽象類的方法可以對Session自定義增刪查改,目前微軟已經有Redis存儲的實現版本了,直接nuget安裝RedisSessionStateProvider包即可,如下:
RedisSessionStateProvider
asp.net session共享
sessionState中將redis配置改爲Redis服務器連接配置,然後我們新建一個mvc視圖來測試多個站點下的Session讀取和共享。Controler代碼如下:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            if (this.HttpContext.Session["MySessionTest"] == null)
            {
                this.HttpContext.Session["MySessionTest"] = string.Format("站點{0}創建的Session", Request.ServerVariables.Get("Server_Port").ToString());
            }
            return View();
        }
    
        public JsonResult GetSession()
        {
            var result = this.HttpContext.Session["MySessionTest"].ToString();
            return Json(new { isok = true, result = result }, JsonRequestBehavior.AllowGet);
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
       
    }

在index action中我們寫入了一個key=MySessionTest的session信息,並且將站點端口信息寫入到了值中,然後提供了一個接口方法用來讀取並返回session[“MySession”]。然後我們看下視圖頁面代碼:

<div class="jumbotron">
    <h1>ASP.NET</h1>
    <p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
    <h3>
        服務器地址:@Request.ServerVariables.Get("Server_Name").ToString()
    </h3>
    <h3>
        服務器端口:@Request.ServerVariables.Get("Server_Port").ToString()
    </h3>
    <div>
        <input id="sessiontxt" /> <button onclick="GetSession()">讀取Session["MySessionTest"]</button>
    </div>
</div>
    function GetSession() {
        $.ajax({
            type: "GET",
            url: "/Home/GetSession",
            xhrFields: { withCredentials: true },
            success: function (data) {
                if (data.isok == true) {
                    $("#sessiontxt").val(data.result);
                }
            }
        });

    }

功能很簡單,顯示當前站點的地址及端口信息,點擊按鈕會調用接口讀取session信息並輸出到文本框中。現在我們做一個測試,我們在IIS上新建三個站點8010/8020/8030都指向這個網站,然後我們分別訪問三個網站查看session獲取結果如下:
負載均衡下的Session共享
Redis共享SessIon
可以看到我們先訪問的8010網站,session在進入8010網站的時候創建了session,在訪問8020網站點擊按鈕獲取session時獲取到的session和8010是相同的,至此我們已經實現了多個站點的Session共享。配合我在上一篇博文中講的負載均衡就實現了分佈式系統各個web站點之間的session共享了。

上一篇:Nginx+IIS實現負載均衡

發佈了12 篇原創文章 · 獲贊 29 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章