一. 简介
学习本节必须有以下几个基础:
(1). Cookie和Session原理:https://www.cnblogs.com/yaopengfei/p/8057176.html
(2). 进程外Session的概念和解决方案:https://www.cnblogs.com/yaopengfei/p/9583168.html
(3). Core MVC中进程外Session的实现:https://www.cnblogs.com/yaopengfei/p/11270816.html
1. 背景
当服务服务器有多台的,用nginx做负载均衡,这样同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,就会出现很多问题,比如说登录成功后续操作拿不到Session里存的权限。
2. 常用解决方案
(1). IP-hash 策略
(2). 借助Cookie来解决
(3). 状态服务器Session,也是进程外Session中的一种,即所有的Session都存放在一台服务器中的内存里,其它应用服务器都访问这一台。
(4). 基于SqlServer的进程外Session
(5). 基于Redis的进程外Session
二. IP-Hash策略
该技术能够将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session,仅需要在修改Nginx的配置,如下图:
该方案有诸多的限制:
(1). ip_hash要求nginx一定是最前端的服务器,否则nginx得不到正确ip,就不能根据ip作hash,比如:使用的是squid为最前端,那么nginx取ip时只能得到squid的服务器ip地址,用这个地址来作分流是肯定错乱的。
(2). 如果nginx后端又有其它负载均衡,将请求又通过另外的方式分流了,那么某个客户端的请求肯定不能定位到同一台session应用服务器上。nginx后端只能直接指向应用服务器,或者再搭一个squid,然后指向应用服务器。
三. Cookie替代策略
1. 原理
session是存放在服务器端的,cookie是存放在客户端的,可以把用户访问页面产生的需要存在session里的信息,存放到cookie里面,就是以cookie为中转站。
访问web服务器A,产生了session然后把它放到cookie里面,当你的请求被分配到B服务器时,服务器B先判断服务器有没有这个session,如果没有,再去看看客户端的cookie里面有没有这个session,如果也没有,说明session真的不存,如果cookie里面有,就把cookie里面的sessoin同步到服务器B,这样就可以实现session的同步了。
2. 分析
这种方法实现起来简单,方便,也不会加大数据库的负担,但是如果客户端把cookie禁掉了的话,那么session就无从同步了,这样会给网站带来损失。
cookie的安全性不高,虽然它已经加了密,但是还是可以伪造的。
这样会导致同一个用户的Session在多个服务器上存储,造成不必要的资源浪费。
四. 状态服务器存储
1. 说明
比默认的进程内Session稍慢一点,比数据库Session快很多,存储空间比进程内的稍大一些, 但毕竟还是存储在内存中的,空间是有限,也会容易被挤爆。即所有的Session都存放在一台服务器中的内存里,其它应用服务器使用Session的时候都访问这一台。
2. 步骤 (以MVC项目为例)
(1). 以win10为例,运行services.msc,打开服务列表,找到【ASP.NET State Service】,右键启动即可。
(2). 相关配置
在<system.Web>节点下加上下面一句话 <sessionState stateConnectionString="tcpip=127.0.0.1:42424" mode="StateServer">
PS:状态服务器端口默认为:42424,在负载均衡下,需要把上述的ip改为一台业务服务器的ip,即其他业务服务器获取Session的时候都上这台上取,同时要把下面注册表中的 AllowRemoteConnection参数改为1,代表其他服务器也可以使用。
如何修改默认端口?
打开注册表 [HKEY_LOCAL_MACHINE/SYSTEM/ControlSet001/Services/aspnet_state/Parameters],其中:Port为端口号,十进制,默认即为42424; AllowRemoteConnection的值 0 代表仅能本机使用,1 代表供其他机器使用.
五. 基于SQLServer 或 Redis
1. 说明
无论是基于SQLServer还是Redis,都是进程外Session,相比进程内Session,基于数据库的Session要慢一些, 但就SQLServer 和 Redis而言,肯定Redis要更快一些,二者的原理是一样的,都是把Session存放到数据库里,当有负载均衡的时候,无论把客户端的请求转发到哪台服务器,最终都是根据SessionId到数据库里取,从而解决了Session共享问题。
下面重点介绍负载均衡下基于Redis的Session共享,以Core MVC为基础事先。(基于SQLServer的详见 https://www.cnblogs.com/yaopengfei/p/9583168.html https://www.cnblogs.com/yaopengfei/p/11270816.html)
2. 基于Redis的案例测试
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。