问题发现
一股脑儿的搞了半个月分布式session,一直误以为
——所谓分布式session不过是多个project共享session这么简单,于是在Maven多模块的项目的基础上基于:
- Spring Session
- Spring data redis
集成了分布式Session功能。直到模块开发完成,进入测试阶段,我才意识到自己是多麽傻叉,根本没有搞懂技术的使用场景就闷头瞎搞。。。
必要条件
使用分布式Session的必要条件是反向代理
(理解反向代理?)
- 简单的,
反向代理
的基础上,单模块(单应用)
下的负载均衡
。
如果以Nginx作为代理服务器,nginx.conf配置方式如下,单模块下负载均衡。
upstream module
{ ip_hash; #ip_hash的方式实现负载均衡
server module.domain1;
server module.domain2;
}
server
{
listen 80;
server_name www.test.com;
location /module{
proxy_pass http://module;
}
}
- 复杂的,
反向代理
的基础上,多模块(多应用)
下的负载均衡
。
如果以Nginx作为代理服务器,nginx.conf配置方式如下,既包含多模块又包含负载均衡。
upstream moduleA
{ ip_hash; #ip_hash的方式实现负载均衡
server moduleA.domain1;
server moduleA.domain2;
}
upstream moduleB
{ ip_hash; #ip_hash的方式实现负载均衡
server moduleB.domain1;
server moduleB.domain2;
}
server
{
listen 80;
server_name www.test.com;
location /moduleA{
proxy_pass http://moduleA;
}
location /moduleB{
proxy_pass http://moduleB;
}
}
- 特殊的,如果
未使用反向代理
,我们可以使用Oauth2.0,JWT 等单点登录(SSO)
框架,来代替分布式Session。
原因
《HttpSession之坑:浏览器如何保证从cookie中解析并发送对应的sessionId到目标Url》
我们了解到:
- 浏览器会根据Url的内容,匹配本地cookie集合的Domain与Path属性;
- 从而得到与Url对应的一些cookie并发送到服务端;
- 服务端再从这些cookie中筛选出
name=seesionid
或jsessionid
的cookie。
所以,对于分布式Session而言,无论你将session存储在任何地方,无论是redis、mysql还是服务端序列化文件,浏览器解析cookie的方式都不会发生变化—— 相同的url请求才会携带相同的cookie
。
又所以,存在于分布式架构的项目,无论是多模块(功能分布)
还是单模块集群(流量分布)
,如果希望共享session,那么就要保证访问任意项目的url中的Domain
与Path
必须相同。而解决方式就是反向代理
—— 隐藏了真正的服务端,目标URL总是指向代理服务器
。
再所以,如果没有使用反向代理
,我们可以选择主动发送sessionid,代替—— 浏览器解析cookie服务端再筛选。此时我们有更合适的解决方案,那就是Oauth2.0,JWT 等单点登录(SSO)
框架。