在上一篇博文中我們通過Nginx+IIS實現了一個簡單的負載均衡,那麼隨之而來的問題就是多個站點在切換時如何共享Session信息,本篇介紹在.net中通過Redis實現分佈式站點的Session共享,並且無需修改原項目的Session讀取方式。
ASP.Net session存儲方式
首先我們看下asp.net中session能採用的存儲方式及優缺點。如下:
- InProc模式(進程內模式) ,爲默認設置。優點是性能高無需跨進程讀取,缺點是依賴asp.net進程,當進程崩潰重啓時會丟失,並且在分佈式的情況下無法多個站點共享。
- StateServer模式(狀態服務器模式)。會話狀態存儲在一個名爲ASP.Net狀態服務的單獨進程中,這確保了在重新啓動Web應用程序時會保留會話狀態,並讓會話狀態可用於網絡中的多個Web服務器。
- SQL Server模式。會話狀態存儲到一個SQL Server數據庫中。這確保了在重新啓動Web應用程序時會保留會話狀態,並讓會話狀態可用於網絡中的多個Web服務器。
- Custom模式。此模式允許您指定自定義存儲提供程序,例如分佈式中常採用自定義模式將站點Session存儲在Redis或Memcached中。
本篇即採用Custom模式自定義存儲提供程序將Session存儲在Redis中。
Redis存儲Session
採用Custom模塊需要修改web.config配置文件中網站的sessionState節點的mode屬性爲Custom,另外我們需要寫一個類實現SessionStateStoreProviderBase抽象類,通過實現抽象類的方法可以對Session自定義增刪查改,目前微軟已經有Redis存儲的實現版本了,直接nuget安裝RedisSessionStateProvider包即可,如下:
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獲取結果如下:
可以看到我們先訪問的8010網站,session在進入8010網站的時候創建了session,在訪問8020網站點擊按鈕獲取session時獲取到的session和8010是相同的,至此我們已經實現了多個站點的Session共享。配合我在上一篇博文中講的負載均衡就實現了分佈式系統各個web站點之間的session共享了。
上一篇:Nginx+IIS實現負載均衡