分布式之Session共享

假装没事ソ 提交于 2020-01-23 18:25:51

在上一篇博文中我们通过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实现负载均衡

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!