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方法上。


非常感谢您花时间读完这篇文章,如果您觉得此文不错,请点一下“推荐”按钮,您的“推荐”就是对我最大的鼓励以及不懈努力的肯定。
本文版权归作者和博客园所有,来源网址:http://www.cnblogs.com/CreateMyself/欢迎各位转载,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利以及小小的鄙视。
出生非贫即贵,你我无能为力,后天若不加以努力赶之超之,又能怪谁呢!自己都靠不住不靠谱,又能靠谁呢!
 
分类: ASP.NET MVC
 
好文要顶 关注我 收藏该文  
3
0
 
(请您对文章做出评价)
 
posted @ 2016-04-19 18:29 Recluse_Xpy 阅读(278) 评论(1) 编辑 收藏
 
评论列表
 

#1楼 2016-04-20 15:32 沈赟 

谢谢分享
 
 
发表评论

昵称:

评论内容:
     
 

退出登录 订阅评论

 

[Ctrl+Enter快捷键提交]

 
 
 

公告

昵称:Recluse_Xpy
园龄:2年4个月
荣誉:推荐博客
粉丝:407
关注:48

 
 

四月 2016

周一

周二

周三

周四

周五

周六

周日

Total Events ToDo Este Mes: 0
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
 
 
 
 
 
 
 

搜索

 
 

积分与排名

  • 积分 - 75551
  • 排名 - 2831

最新评论

 
 
Copyright ©2016 Recluse_Xpy

喜欢请打赏

扫描二维码打赏

支付宝打赏

了解更多

MVC之Session State性能的更多相关文章

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

    前言 这一节翻译一篇有关Session State性能问题的文章,非一字一句翻译. 话题 不知道我们在真实环境中是否用到了Session State特性,它主要用来当在同一浏览器发出多个请求时来存储数 ...

  2. 关于ASP.NET Session State Server

    最近公司开发的一个网站因为访问量增大,需要添加多台Web Server来进行负载均衡. 但是在做负载均衡前需要将一些原来固定存储在单台机器上的东西分离出来,使之能单独存在在一个独立的机器上,其中就有S ...

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

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

  4. easyui datagrid 禁止选中行 EF的增删改查(转载) C# 获取用户IP地址(转载) MVC EF 执行SQL语句(转载) 在EF中执行SQL语句(转载) EF中使用SQL语句或存储过程 .net MVC使用Session验证用户登录 PowerDesigner 参照完整性约束(转载)

    easyui datagrid 禁止选中行   没有找到可以直接禁止的属性,但是找到两个间接禁止的方式. 方式一: //onClickRow: function (rowIndex, rowData) ...

  5. Session State Pattern会话状态模式

    Client Session State 客户会话状态. 在Client端保存会话状态. 运行机制 Client在每次请求时会把所有的会话数据传给Server,Server在响应时把所有的会话状态传给 ...

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

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

  7. Spring MVC中Session的正确用法<转>

    Spring MVC是个非常优秀的框架,其优秀之处继承自Spring本身依赖注入(Dependency Injection)的强大的模块化和可配置性,其设计处处透露着易用性.可复用性与易集成性.优良的 ...

  8. Unable to make the session state request to the session state server处理

    Server Error in '/' Application. Unable to make the session state request to the session state serve ...

  9. 【转】Spring MVC中Session的正确用法之我见

    Spring MVC是个非常优秀的框架,其优秀之处继承自Spring本身依赖注入(Dependency Injection)的强大的模块化和可配置性,其设计处处透露着易用性.可复用性与易集成性.优良的 ...

随机推荐

  1. GitHub详解(转)

    GitHub 是一个共享虚拟主机服务,用于存放使用Git版本控制的软件代码和内容项目.它由GitHub公司(曾称Logical Awesome)的开发者Chris Wanstrath.PJ Hyett ...

  2. (升级版)Spark从入门到精通(Scala编程、案例实战、高级特性、Spark内核源码剖析、Hadoop高端)

    本课程主要讲解目前大数据领域最热门.最火爆.最有前景的技术——Spark.在本课程中,会从浅入深,基于大量案例实战,深度剖析和讲解Spark,并且会包含完全从企业真实复杂业务需求中抽取出的案例实战.课 ...

  3. [置顶] 提高生产力:Web开发基础平台WebCommon的设计和实现

    Web开发中,存在着各种各样的重复性的工作.为了提高开发效率,不在当码农,我在思考和实践如何搭建一个Web开发的基础平台. Web开发基础平台的目标和功能 1.提供一套基础的开发环境,整合了常用的框架 ...

  4. JavaScript-4.6鼠标事件监听,获取鼠标坐标window.event---ShinePans

    <html> <head> <meta http-equiv="content-type" content="text/html" ...

  5. Flex上传文件

    前几天写了一篇jsp页面利用ajaxFileUpload上传文件.如今把flex上传页面也分享出来: 前台页面 <?xml version="1.0" encoding=&q ...

  6. PLSQL数据导入

    导入数据 (1)      首先以管理员身份登录plsql; (2)      新建命令窗口 (3)      创建用户,设置帐号,密码 创建语句:create user usernameidenti ...

  7. Android 3d云标签

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWluZ3l1ZV8xMTI4/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  8. Error:The SDK Build Tools revision (19.0.3) is too low for project ':app'. Minimum required is 19.1.

    今天更新了一下AndroidStudio, 结果编译程序时报错, 错误如下: Error:The SDK Build Tools revision (19.0.3) is too low for pr ...

  9. 【问题解决】syntax error: unexpected end of file或-bash: ./full_build.sh: /bin/bash^M: bad interpreter: No

    在阅读的过程中有不论什么问题,欢迎一起交流 邮箱:1494713801@qq.com    QQ:1494713801 运行一个脚本full_build.sh 时, 一直是提示我: -bash: ./ ...

  10. fopen()功能

    1.2 文件输入和输出功能 键盘.显示器.打印机.磁盘驱动器和其他逻辑器件, 输入和输出可以通过文件管理方法可以完成. 最经常使用的编程是一个磁盘文件, 因此,这一部分主要是基于磁盘文件, 简介Tur ...