2019独角兽企业重金招聘Python工程师标准>>>

应用部署结构(精简):

站点部署在Nginx后面,以Nginx作为反向代理,不希望在Nginx上设置ip_hash,实现比较真实的负载均衡效果。

这时考虑到需要让site1site2同时共享会话信息,进行如下的配置:

默认情况下asp.net站点的会话模式是采用Inproc模式,这种模式在站点因IIS重启会导致丢失用户会话(已经登陆的用户会自动重定向到登陆页面),在本次实践中使用SqlServer模式

创建会话数据库(独立于应用):

aspnet_regsql.exe -S server_ip -E -ssadd -sstype c -d dbname

更多参数可以参考命令的帮助aspnet_regsql.exe /?,通常路径在**C:\Windows\Microsoft.NET\Framework64\{.net_version}**下

配置如下:

<sessionState mode="SQLServer" sqlConnectionString="server=server_ip;database=dbname;uid=user;pwd=pwd;" allowCustomSqlDatabase="True" cookieless="false" timeout="20" />

会话数据库的表ASPStateTempApplications中存放应用的信息(appId和AppName),每一个站点一条记录,我两个站点分别使用该数据库所以有两条记录,如图:

通过以上的配置, 貌似完成了会话的共享,这时候通过NginxIP地址发送两个请求到服务器(一个登陆,一个获取用户考试列表)。通过Nginx的日志发现两次请求被分发到两台不同的后端服务器:

从图中可以看出第一次请求是192.168.2.2:80803这个站点处理,第二个请求被192.168.2.5:8083这个站点处理。明明已经设置了会话共享为什么第二次请求被提示为未登录。检查是否登陆的代码如下:

 public class WebApiCheckLoginFilterAttribute : ActionFilterAttribute{public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext){LoginService service = new LoginService();string controllerName = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName;string actionName = actionContext.ActionDescriptor.ActionName;bool isAuthAction = controllerName.Equals("ExamAPI") && actionName.Equals("Login");if (!isAuthAction){HttpSessionState Session = System.Web.HttpContext.Current.Session;if (Session["user"] == null){throw new HttpException((int)HttpStatusCode.NonAuthoritativeInformation, "未登录用户或已在其他设备中登录");}if (!service.IsOnline(Model.DeviceType.Phone, Session.SessionID)){throw new HttpException((int)HttpStatusCode.NonAuthoritativeInformation, "未登录用户或已在其他设备中登录");}}base.OnActionExecuting(actionContext);}}

上述代码是为了检查如果session['user']==null,就会提示是未登陆。已经配置了会话共享为什么session['user']还是获取不到用户对象?通过各种尝试发现asp.net在处理session的时候会根据站点的AppId加上浏览器上的SessionId在数据库表([ASPStateTempSessions])中创建会话记录,SessionId的值如下:

0kf0zoq4to3h0z0b1eztw43s28d8c075
  • 28d8c075 是AppId685293685的16进制(对应的AppId)
  • 0kf0zoq4to3h0z0b1eztw43s是客户端cookie中存放的sessionid

通过查看存储过程[dbo].[TempGetAppID]的代码,发现asp.net会通过每个站点的AppName(见表ASPStateTempApplications)去获取AppId,然后将SessionId+AppId(16进制)作为主键插入到表ASPStateTempSessions中,这样的处理逻辑是保证一个会话数据库会被N个站点共同使用,不用每个站点创建自己的会话数据库。隐藏的问题是如果站点的AppName不一样会导致获取的AppId不一样达不到会话共享的目的。

验证过程如下:向Nginx发送两个请求(一个登陆,一个获取考试列表)会在ASPStateTempSessions表中产生两条记录,正常情况应该两个请求也应该只产生一条会话记录。

为了保证只产生一条会话记录可以通过让site1site2的AppName保持一致,每次通过存储过程[dbo].[TempGetAppID]获取的AppId都是同一个。 修改方式为:

修改完成后,再次发送两个请求(一个登陆,一个获取考试列表),两个请求经过Nginx分发到两个站点后在ASPStateTempSessions只产生一条会话记录,这样才真正的实现会话的一致性。

配置machineKey,在做asp.net站点集群的时候如果站点中使用到cookieviewstate的话需要配置machineKey来确保多台机器共享验证和ViewState.每个节点上的machineKey配置必须一致

按照MSDN的标准说法:“对密钥进行配置,以便将其用于对 Forms 身份验证 Cookie 数据和视图状态数据进行加密和解密,并将其用于对进程外会话状态标识进行验证.加密和解密使用的就是machineKey

生成machineKey的代码

public static string CreateMachineKey(int length){byte[] random = new byte[length / 2];RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();rng.GetBytes(random);StringBuilder builder = new StringBuilder();for (int i = 0; i < random.Length; i++){builder.Append(string.Format("{0:X2}", random[i]));}return builder.ToString();}string decryptionKey= CreateMachineKey(48);string validationKey = CreateMachineKey(128);

web.config配置内容

<system.web><compilation targetFramework="4.0" /><machineKey validationKey="validationKey" decryptionKey="decryptionKey"/>
...other...</system.web>

小结

asp.net 站点的会话模式如果选用SqlServer的话,需要保证站点群(可能有N个站点)通过[dbo].[TempGetAppID]存储过程获取AppId后的结果是相同的。可以通过修改存储过程,也可以通过修改AppName。

转载于:https://my.oschina.net/hulingfeng/blog/1525737

asp.net mvc4开启SqlServer 会话共享模式相关推荐

  1. C#毕业设计——基于C#+asp.net+sqlserver基于C2C模式的网上购物系统设计与实现(毕业论文+程序源码)——网上购物系统

    基于C#+asp.net+sqlserver基于C2C模式的网上购物系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于C#+asp.net+sqlserver基于C2C模式的网上购物系统 ...

  2. Oracle启用远程访问开启共享模式

    注 **注:**2016-01-22 实践证明,互联网不一定靠谱啊[emoji:笑哭]. 一直以为启用远程访问需要开启共享模式,但自己又做了多种尝试,发现他们是错的啊[大片纸],局域网内远程访问实际上 ...

  3. ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存

    ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存 原文:ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存 ASP.Net MVC4+Memc ...

  4. [翻译]ASP.NET MVC4新特性之脚本压缩和合并

    2019独角兽企业重金招聘Python工程师标准>>> [翻译]ASP.NET MVC4新特性之脚本压缩和合并 目前主流浏览器限制客户端对同一域名只能同时发起6(PS:原文如此)个H ...

  5. Asp.Net MVC4的学习概况

    周一正式开始了毕业工作.然后学习调试了近4天,刚刚总算在同事的帮助下做出了一个基于Asp.Net MVC4的Hello World显示. 这是一篇最为基础的记录教程,记录内容可能有点混乱,旨在能在刚调 ...

  6. Nginx+Tomcat实现高可用和Session会话共享

    一.简介 对于生产环境有了一定规模的tomcat集群业务来说,要实现session会话共享,比较稳妥的方式就是使用数据库持久化session.为什么要持久化session(共享session)呢?因为 ...

  7. 【翻译转载】【官方教程】Asp.Net MVC4入门指南(2):添加一个控制器

    2. 添加一个控制器 · 原文地址:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-c ...

  8. 0821Cache Buffers chains与共享模式疑问4

    [20170821]Cache Buffers chains与共享模式疑问4.txt --//昨天别人问的问题,就是在读读模式下,访问相同数据块,11.2.0.4不再出现cache buffers c ...

  9. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(10)-系统菜单栏[附源码]

    构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(10)-系统菜单栏[附源码] 原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后 ...

最新文章

  1. JavaScript cookie
  2. 解决GitHub未配置SSH key提示错误信息
  3. 146. LRU Cache
  4. 深入Java核心 Java内存分配原理精讲
  5. java中 静态方法与成员方法何时使用
  6. UVa 3349 Snowflake Snow Snowflakes(Hash)
  7. python pytest mark.parametrize
  8. Python datetime timedelta
  9. bz1968 1968: [Ahoi2005]COMMON 约数研究
  10. extJS4.2.0 Json数据解析,嵌套及非嵌套(二)
  11. 酷派android升级失败,酷派大神X7刷机失败变砖开不了机 救砖教程
  12. linux 安装Julia
  13. 体育成绩统计——20180801模拟赛T3
  14. 机械键盘黑轴红轴青轴茶轴区别 机械键盘黑轴红轴青轴茶轴哪个好
  15. 海思开发:yolo v5s :pytorch->onnx->caffe->nnie
  16. html中写jq,在jQuery中,能够操作HTML代码及其文本的方法是()
  17. 游戏设计艺术 第2版 第30章 读书笔记
  18. GraphQL的认识与使用
  19. 我的求职历程-----求职总结
  20. 读后感: 懈寄生---走出软件作坊:三五个人十来条枪 如何成为开发正规军(十四)

热门文章

  1. cmd管道无法接收特定程序返回值_渗透不会反弹shell?来教你写一个cmd的shell
  2. recv原理、高阶版黏包解决方案、基于UDP的socket通信
  3. [BZOJ]3173: [Tjoi2013]最长上升子序列
  4. spring boot 整合 (全)
  5. mysql盲注学习-1
  6. spring-boot 速成(8) 集成druid+mybatis
  7. 《CLR via C#》之线程处理——线程基础
  8. 表单的get和post使用情景
  9. JavaWeb -- Session实例 -- 自动登录 和 防止表单重复提交(令牌产生器) MD5码
  10. 邮件群发工具的编写(二)数据的保存