ASP.NET MVC之Session State性能问题(七)

简介:

前言

这一节翻译一篇有关Session State性能问题的文章,非一字一句翻译。

话题

不知道我们在真实环境中是否用到了Session State特性,它主要用来当在同一浏览器发出多个请求时来存储数据,在现在我们更多的为了避免整个页面刷新,Web应用程序更多倾向于利用高扩展性的Ajax,但是不知道我们是否注意到当我们使用Session数据多次请求MVC上的Action方法时产生的性能问题呢?

将Session放入上下文中(Put Session into the Context)

在进行代码演示时我们首先得知道Session的工作原理:当一个新请求第一次到达服务器时,显然在此之前Cookie中没有SessionId的,此时服务器将创建一个新的Session标识,通过如下:

System.Web.HttpContext.Current.Session.SessionID

但是并不意味着当有多个请求发送到服务器上时,服务器都会保存一个Session Cookie。只是在Session中保存具体请求的数据,换言之,ASP.NET Framework会首先会添加Session Cookie到响应流中,此时需要保存的数据将被保存在Session中。

因此,说到这里好像和我们要讲的主题半毛钱关系都没有,那跟我们的性能有什么关系呢?ASP.NET能够处理来自同一浏览器的多个请求,如下:

在上述图片中,当浏览器未发出请求时显然在服务器上不会存储任何Session数据,如果服务器存储了一些数据在Session中,此时将会添加一个Session Cookie到响应流中,接下来所有的子请求使用相同的Session Cookie,同时会以队列的形式依次等待被处理。

我们能够想象到一种很常见的场景,要是多个请求同时去读取或修改相同的Session值,此时则会造成不一致的数据。接下来进入我们话题演示时间。

代码演示

我们在控制器中给出如下代码:

复制代码
    [OutputCache(NoStore = true, Duration = 0)] //不缓存数据
    public class HomeController : Controller
    {
        public List<string> boxes = new List<string>() { "red", "green", "blue", "black", "gray", "yellow", "orange" };
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public string GetBox() //随机获取集合中颜色
        {
            System.Threading.Thread.Sleep(10);
            Random rnd = new Random();
            int index = rnd.Next(0, boxes.Count);

            return boxes[index]; 
        }

        public ActionResult StartSession() //启动Session并存值
        {
            System.Web.HttpContext.Current.Session["Name"] = "Chris";

            return RedirectToAction("Index");
        }
    }
复制代码

接下来我们利用AngularJS在视图中发出Ajax请求以及其他操作,我们看看视图中代码:

复制代码
<body ng-controller="asyncCtrl" ng-init="getBoxes()">
    <nav role="navigation" class="navbar navbar-default navbar-fixed-top">
        <div class="container-fluid">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" data-target="#navbarCollapse" data-toggle="collapse" class="navbar-toggle">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
            </div>
            <!-- Collection of nav links and other content for toggling -->
            <div id="navbarCollapse" class="collapse navbar-collapse">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="#">Performace testing</a></li>
                    <li>
                        @Html.ActionLink("Start Session", "StartSession")
                    </li>
                    <li>
                        <a class="links" ng-click="getBoxes()">Not resolved</a>
                    </li>
                    <li>
                        <a class="links" ng-click="getBoxes(true)">Resolved</a>
                    </li>
                    <li>
                        <form class="navbar-form">
                            <label class="checkbox" style="margin-top:5px">
                                @Html.CheckBox("isSessionNewChk", Session.IsNewSession, new { @disabled = "disabled" })
                                Is Session new
                            </label>
                        </form>
                    </li>
                </ul>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#">{{boxes.length}} Boxes</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <br /><br /><br />
    <div class="container">
        <div class="row">
            <div id="boxesContainer" ng-repeat="color in boxes track by $index">
                <div class="box" ng-class="color" />
            </div>
        </div>
        <br />
        <div class="row">
            <div id="timeOccured" ng-show="showResults" class="alert" ng-class="isResolved()" ng-bind="timeElapsed"></div>
        </div>
    </div>
    <script src="~/Scripts/app.js"></script>
</body>
复制代码

接下来我们看看 app.js 

复制代码
angular.module('asyncApp', [])
    .value('mvcuri', 'http://localhost:49588/home/getbox')
    .value('mvcurisessionresolved', 'http://localhost:49588/SessionResolved/getbox')
    .controller('asyncCtrl', function ($http, $scope, mvcuri, mvcurisessionresolved) {

        $scope.boxes = [];
        $scope.showResults = false;
        var uri;

        $scope.getBoxes = function (resolved) {
            var start = new Date();
            var counter = 300;

            
            if (resolved)
                uri = mvcurisessionresolved;
            else
                uri = mvcuri;

            // Init variables
            $scope.boxes = [];
            $scope.showResults = false;
            $scope.timeElapsed = '';

            for (var i = 0; i < 300; i++) {
                $http.get(uri)
                    .success(function (data, status, headers, config) {
                        $scope.boxes.push(data);
                        counter--;

                        if (counter == 0) {
                            var time = new Date().getTime() - start.getTime();
                            $scope.timeElapsed = 'Time elapsed (ms): ' + time;
                            $scope.showResults = true;
                        }
                    })
                        .error(function (error) {
                            $scope.timeElapsed = error.Message;
                        }).finally(function () {
                        });
            }
        };

        $scope.isResolved = function () {
            return uri == mvcuri ? 'alert-danger' : 'alert-success';
        }

    });
复制代码

上述AngularJS脚本比较简单就不叙述。接下来再创建一个控制器 SessionResolvedController 来进行比较。

复制代码
    [OutputCache(NoStore = true, Duration = 0)]
    public class SessionResolvedController : Controller
    {
        public List<string> boxes = new List<string>() { "red", "green", "blue", "black", "gray", "yellow", "orange" };

        public string GetBox()
        {
            try
            {
                System.Threading.Thread.Sleep(10);
                Random rnd = new Random();
                int index = rnd.Next(0, boxes.Count);

                return boxes[index];
            }
            catch(Exception ex)
            {
                return "red";
            }
        }
    }
复制代码

此时我们看看运行效果:

当我们运行程序时,此时复选框是勾上的,说明此时还未有添加数据到Session中,接下来我们点击 Start Session 看看效果:

上述我们是启动Start Session并控制整发出300个Ajax请求并返回随机颜色。我们看到花了8722毫秒。 

接下来我们点击 Not resolved 看看耗时多少,如下:

耗时8166毫秒,看来和启动Session没什么区别可言。因为每个到服务器的请求都有一个Session Cookie,此时所有的请求将会被依次处理正如我们之前所描述的那样,所以接下来我们进行如下操作:

    [SessionState(SessionStateBehavior.Disabled)]
    public class SessionResolvedController : Controller
    {.....}

我们禁用SessionState看看效果:

注意:上述程序运行建议在Release模式下进行演示,可能这样的效果更加明显。

参考

ASP.NET MVC Session state Performance Issue

结语

当有多个请求发送到服务器时此时若进行Session操作将会对性能产生一定影响。我们通过设置 [SessionState(SessionStateBehavior.Disabled)] 特性最终验证了这一观点。但是这样设置后我们将无法获取Session中的值。所以在请求数量较多的情况下,建议对于Ajax请求使用Web APi来完成,我们通过Web APi来接收Ajax请求,可以使用Session中的数据来渲染视图或者提交到数据或者参数到MVC控制器的Action方法上。






本文转自Jeffcky博客园博客,原文链接:http://www.cnblogs.com/CreateMyself/p/5408400.html,如需转载请自行联系原作者

目录
相关文章
|
SQL 缓存 开发框架
分享一个 .NET EF6 应用二级缓存提高性能的方法
分享一个 .NET EF6 应用二级缓存提高性能的方法
140 0
|
10月前
|
算法 Java 测试技术
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
226 13
|
10月前
|
监控 前端开发 API
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
237 5
|
10月前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
425 13
|
11月前
|
开发框架 安全 .NET
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱。它不仅加速了应用开发进程,提升了开发质量和可靠性,还促进了创新和业务发展,培养了专业人才和技术社区,为软件开发和数字化转型做出了重要贡献。
177 5
|
11月前
|
传感器 人工智能 供应链
.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。
本文深入探讨了.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。通过企业级应用、Web应用及移动应用的创新案例,展示了.NET在各领域的广泛应用和巨大潜力。展望未来,.NET将与新兴技术深度融合,拓展跨平台开发,推动云原生应用发展,持续创新。
132 4
|
11月前
|
机器学习/深度学习 人工智能 Cloud Native
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台。本文深入解析 .NET 的核心优势,探讨其在企业级应用、Web 开发及移动应用等领域的应用案例,并展望未来在人工智能、云原生等方面的发展趋势。
211 3
|
11月前
|
开发框架 安全 Java
.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力
本文深入探讨了.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力。.NET不仅支持跨平台开发,具备出色的安全性和稳定性,还能与多种技术无缝集成,为企业级应用提供全面支持。
318 3
|
11月前
|
人工智能 Java 编译器
.NET 9 发布 性能提升、AI 支持与全方位改进
【11月更文挑战第5天】.NET 9 引入了多项改进,包括性能提升、AI 支持和全方位功能优化。性能方面,编译器增强、服务器 GC 优化、矢量化和硬件支持等提升了执行效率。AI 方面,新增学习材料、合作伙伴生态、原生支持和生成式 AI 集成。此外,.NET Aspire 组件升级、编程语言新功能和开发工具更新进一步提升了开发体验。
235 3
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
199 7