前言

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

话题

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

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

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

  1. System.Web.HttpContext.Current.Session.SessionID

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

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

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

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

代码演示

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

  1. [OutputCache(NoStore = true, Duration = )] //不缓存数据
  2. public class HomeController : Controller
  3. {
  4. public List<string> boxes = new List<string>() { "red", "green", "blue", "black", "gray", "yellow", "orange" };
  5. // GET: Home
  6. public ActionResult Index()
  7. {
  8. return View();
  9. }
  10.  
  11. public string GetBox() //随机获取集合中颜色
  12. {
  13. System.Threading.Thread.Sleep();
  14. Random rnd = new Random();
  15. int index = rnd.Next(, boxes.Count);
  16.  
  17. return boxes[index];
  18. }
  19.  
  20. public ActionResult StartSession() //启动Session并存值
  21. {
  22. System.Web.HttpContext.Current.Session["Name"] = "Chris";
  23.  
  24. return RedirectToAction("Index");
  25. }
  26. }

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

  1. <body ng-controller="asyncCtrl" ng-init="getBoxes()">
  2. <nav role="navigation" class="navbar navbar-default navbar-fixed-top">
  3. <div class="container-fluid">
  4. <!-- Brand and toggle get grouped for better mobile display -->
  5. <div class="navbar-header">
  6. <button type="button" data-target="#navbarCollapse" data-toggle="collapse" class="navbar-toggle">
  7. <span class="sr-only">Toggle navigation</span>
  8. <span class="icon-bar"></span>
  9. <span class="icon-bar"></span>
  10. <span class="icon-bar"></span>
  11. </button>
  12. </div>
  13. <!-- Collection of nav links and other content for toggling -->
  14. <div id="navbarCollapse" class="collapse navbar-collapse">
  15. <ul class="nav navbar-nav">
  16. <li class="active"><a href="#">Performace testing</a></li>
  17. <li>
  18. @Html.ActionLink("Start Session", "StartSession")
  19. </li>
  20. <li>
  21. <a class="links" ng-click="getBoxes()">Not resolved</a>
  22. </li>
  23. <li>
  24. <a class="links" ng-click="getBoxes(true)">Resolved</a>
  25. </li>
  26. <li>
  27. <form class="navbar-form">
  28. <label class="checkbox" style="margin-top:5px">
  29. @Html.CheckBox("isSessionNewChk", Session.IsNewSession, new { @disabled = "disabled" })
  30. Is Session new
  31. </label>
  32. </form>
  33. </li>
  34. </ul>
  35. <ul class="nav navbar-nav navbar-right">
  36. <li><a href="#">{{boxes.length}} Boxes</a></li>
  37. </ul>
  38. </div>
  39. </div>
  40. </nav>
  41. <br /><br /><br />
  42. <div class="container">
  43. <div class="row">
  44. <div id="boxesContainer" ng-repeat="color in boxes track by $index">
  45. <div class="box" ng-class="color" />
  46. </div>
  47. </div>
  48. <br />
  49. <div class="row">
  50. <div id="timeOccured" ng-show="showResults" class="alert" ng-class="isResolved()" ng-bind="timeElapsed"></div>
  51. </div>
  52. </div>
  53. <script src="~/Scripts/app.js"></script>
  54. </body>

接下来我们看看 app.js

  1. angular.module('asyncApp', [])
  2. .value('mvcuri', 'http://localhost:49588/home/getbox')
  3. .value('mvcurisessionresolved', 'http://localhost:49588/SessionResolved/getbox')
  4. .controller('asyncCtrl', function ($http, $scope, mvcuri, mvcurisessionresolved) {
  5.  
  6. $scope.boxes = [];
  7. $scope.showResults = false;
  8. var uri;
  9.  
  10. $scope.getBoxes = function (resolved) {
  11. var start = new Date();
  12. var counter = 300;
  13.  
  14. if (resolved)
  15. uri = mvcurisessionresolved;
  16. else
  17. uri = mvcuri;
  18.  
  19. // Init variables
  20. $scope.boxes = [];
  21. $scope.showResults = false;
  22. $scope.timeElapsed = '';
  23.  
  24. for (var i = 0; i < 300; i++) {
  25. $http.get(uri)
  26. .success(function (data, status, headers, config) {
  27. $scope.boxes.push(data);
  28. counter--;
  29.  
  30. if (counter == 0) {
  31. var time = new Date().getTime() - start.getTime();
  32. $scope.timeElapsed = 'Time elapsed (ms): ' + time;
  33. $scope.showResults = true;
  34. }
  35. })
  36. .error(function (error) {
  37. $scope.timeElapsed = error.Message;
  38. }).finally(function () {
  39. });
  40. }
  41. };
  42.  
  43. $scope.isResolved = function () {
  44. return uri == mvcuri ? 'alert-danger' : 'alert-success';
  45. }
  46.  
  47. });

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

  1. [OutputCache(NoStore = true, Duration = )]
  2. public class SessionResolvedController : Controller
  3. {
  4. public List<string> boxes = new List<string>() { "red", "green", "blue", "black", "gray", "yellow", "orange" };
  5.  
  6. public string GetBox()
  7. {
  8. try
  9. {
  10. System.Threading.Thread.Sleep();
  11. Random rnd = new Random();
  12. int index = rnd.Next(, boxes.Count);
  13.  
  14. return boxes[index];
  15. }
  16. catch(Exception ex)
  17. {
  18. return "red";
  19. }
  20. }
  21. }

此时我们看看运行效果:

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

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

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

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

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

我们禁用SessionState看看效果:

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

参考

ASP.NET MVC Session state Performance Issue

结语

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

ASP.NET MVC之Session State性能问题(七)的更多相关文章

  1. MVC之Session State性能

    ASP.NET MVC之Session State性能问题(七)   前言 这一节翻译一篇有关Session State性能问题的文章,非一字一句翻译. 话题 不知道我们在真实环境中是否用到了Sess ...

  2. 转载ASP.NET MVC中Session的处理机制

    本文章转载自 http://www.cnblogs.com/darrenji/p/3951065.html ASP.NET MVC中的Session以及处理方式   最近在ASP.NET MVC项目中 ...

  3. 实现Asp.net Mvc分布式Session Redis群集

    Redis群集实现Asp.net Mvc分布式Session Session的缺点 众所周知Asp.net Session默认存储在IIS中,IIS的重启会导致Session丢失. 如果你的网站使用了 ...

  4. Asp.net Mvc 自定义Session (二)

    在 Asp.net Mvc 自定义Session (一)中我们把数据缓存工具类写好了,今天在我们在这篇把 剩下的自定义Session写完 首先还请大家跟着我的思路一步步的来实现,既然我们要自定义Ses ...

  5. Redis群集实现Asp.net Mvc分布式Session

    Session的缺点 众所周知Asp.net Session默认存储在IIS中,IIS的重启会导致Session丢失. 如果你的网站使用了session,当网站并发过大时可能引起溢出. 配置Redis ...

  6. ASP.NET MVC Controller Session问题

    发现问题 最近在项目中遇到这样一个问题,一直没办法重现,所以几天都没有解决. 测试那边给出的问题是这样的:每天早上来的时候,第一次通过单点登录到系统的时候,总会跳转回登录界面,再次登录就好了.当时给我 ...

  7. 003.ASP.NET MVC集中管理Session

    原文链接:http://www.codeproject.com/Tips/790387/Session-in-ASP-NET-MVC 1.前言 今天有得有失啊,看到这篇,专心记下里面的精华吧 2.一般 ...

  8. Asp.net Mvc 自定义Session (一),

    大家都知道用系统默认的session 会存在这样的问题 如果用户过多的话 session 会自动消亡,而且不能支持分布式和集群. 这系列博客主要讲解  怎样 解决用户过多的session自动消亡,和分 ...

  9. [2014-02-23]Asp.net Mvc分布式Session存储方案

    要玩集群的时候,怎么处理会话状态Session? InProc模式的sessionState是不能用了,因为这是在web服务器本机进程里的,会造成各节点数据不一致.除非在分流的时候用ip hash策略 ...

随机推荐

  1. JavaScript-String基础知识

    1.字符串可以0个或多个字符串放在一起:     " ' '    ".'""' . "\"\""       2.写法 ...

  2. 速度极快的导出excel

    public class Export2Excel { #region [导出文件,使用文件流] /// <summary> /// 导出文件,使用文件流.该方法使用的数据源为DataTa ...

  3. HDU--航海舰队

    海舰队 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  4. iptables 思维导图 (zz)

  5. myeclipse导入项目出现jquery错误(有红叉)

    今天导入了一个项目,但是进去之后jquery出现了红叉,如图(事实上在我没调好之前两个jquery文件都有叉号) 怎么调呢?右键jquery文件,选择MyEclipse->Exclude Fro ...

  6. iphone 下滚动条卡顿解决办法

    -webkit-overflow-scrolling:touch; -webkit-text-size-adjust:none;

  7. Ajax全面基础学习(一)

    快捷方法: $.get(url,[data],[callback],[type])get方法的[data]将被链在url后面[callback]是请求成功后的回调,可以得到响应数据,如果请求失败,看不 ...

  8. 通过js实现回到顶部功能

    许多商城网址,当我们滚动到一定高度时,我们会发现一般会出现一个回到顶部的js选项,点击轻松实现回到顶部,交互效果会显得比较人性化,且回到顶部过程中若在滚动滚动条时可以停止滚动,现在让我们来实现吧 我总 ...

  9. LB 负载均衡的层次结构

    作为后端应用的开发者,我们经常开发.调试.测试完我们的应用并发布到生产环境,用户就可以直接访问到我们的应用了.但对于互联网应用,在你的应用和用户之间还隔着一层低调的或厚或薄的负载均衡层软件,它们不显山 ...

  10. Lesson 4 An existing trip

    Text I have just received a letter from my brother,Tim. He is in Australia. He has been there for si ...