这几天一直在看集群和分布式中解决sesstion共享的问题?所以总结了一些自己的理解不知道对不对?
1.session共享现在比较流行的方案是,存储到redis中(key 对应sessionID 、value对应session的值),即集中式管理session数据,让所以的服务器都统一到一个地方去获取session数据。
2.根据redis存储session的方式,要获取对应的session数据,每个服务器必须享有相同的sessionID,怎么享有相同的sessionID呢,这里主要分为几种情况:
(1)、集群:在集群系统中,我们一般是一个域名/IP对应多个服务器,通过NGINX实现负载均衡,由于只有一个域名,所以不管是哪台服务器设置sesstion,生成的sessionID都是保存在客户端同一个域名下的。因此,每次请求服务器的时候,cookie中sessionID都是一样的,这样的话就解决了,各个服务器接收到的sessionID是相同的。
(2)、分布式:在分布式系统中存在一个跨域的问题,比如说:淘宝网,里面就有很多子模块系统(login.taobao.com、list.taobao.com等等)但是它们有个特点就是所有的域名都是在同一个顶级域名下的二级域名,要实现sessionID共享,只需要解决其它子域名可以访问同一域下的cookie。所以只需要对 COOKIE 的域(domain)进行特殊地设置即可,以php为例:
如:www.a.com 和 i.a.com 都属于域 .a.com,那么我们就可以设置 COOKIE 的域为 .a.com,这样 www.a.com、i.aaa.com 等等都可以访问此 COOKIE。PHP 代码中的设置方法如下:
ini_set('session.cookie_domain', '.a.com');
这样各个系统共享同一客户端 SESSION ID 的目的就达到了。
还有一个跨域的情况就是完全跨域:(www.a.com www.b.com)
通过URL参数实现跨域信息传递
如果考虑到广泛的兼容性,可最直接的通过url参数传递的方式,重定向到b的url中,b域获取cookie信息,在该域中进行写入。这就只涉及到把a域的信息传递到b中,使用URL传参便可以实现。
浏览器通过访问www.a.com/tg?from=http://www.b.com/set_cookie 重定向到b域的set_cookie方法,传入token参数。这种方法最具有广泛性。
当然,这些方法可行,但很麻烦,restful api提出来的时候,就已经要求所有请求都是无状态的,但实际上这点实际实现中被违反最多。所有session都是有状态的,都是不利于集群的,不管你是把session放在内存还是放在redis还是其他什么数据库中。一定要用session的话,不是不可以,只是会带来很多麻烦。
所以,最优的解决方案是,回归restful,取消session。比如用jwt之类的,原来session保存的数据直接发给前端,每次前端都把这些数据传回。这样后台api完全无状态,最有利于集群分布式处理。