在网站的演进过程中,当我们的单一应用服务器无法再负担众多请求跟响应的时候,这时候,我们就会考虑,要不要搞个服务器集群,这时候,我们又加了台服务器,为了按照一定权重分发请求跟响应,我们又加上了负载均衡设备,本来以为,完美!但是,就像改bug那样,修复掉一个bug,很有可能就产生了新的 bug。
当引入了新的中间层,我们似乎解决了服务器因为自身性能问题,无法处理更多请求跟响应。但是,这里出现了一个很细节的问题,以上图为例,每次client开启一个会话,就会产生一个session,代表当前客户端跟应用服务器的一次会话,并且生成唯一标示——sessionId。
now imagine when you are surfing with your chrome,you open a tab ,enter a url:这时候你产生一个request对象,这个对象携带着你的sessionid(标识会话),沿着途中的蓝线,到了左边的服务器上,左边的服务器处理完成之后,给你一个response,之后你的client(your chrome)呈现出一个结果给你,you say:(⊙o⊙)哦,前两天收藏的这个mini skirt 降价啦!买买买!!!
接着你提交订单,你的请求先到了负载均衡设备上,接下来,它要将你的请求发送到应用服务器集群中的一个服务器上,now,问题就出现在这里,上一次我与服务器进行会话的时候,使用的是第一个应用服务器,但是由于我没规定负载均衡设备该怎么分发请求,所以,如果负载均衡设备将你的请求发送到第二个应用服务器上,但是我这次会话的session还在第一个应用服务器上,(⊙o⊙)…发现了什么吧。。。
打了这么多字,其实就是想说明一个问题,你引入了负载均衡设备,还要为负载均衡设备配置让我的同一个会话,落在相同的应用服务器上。
在没有负载均衡设备之前,因为我们只有一台应用服务器,我们的每次请求都是落在同一个服务器上,session也是都在这个服务器,我们的每一次会话请求都在这一个服务器上进行处理。
沿用这个简单思路,如果我们在负载均衡设备上,设置这样的规章:让每次请求响应均被负载均衡设备发送到相同的服务器进行处理,这样,我们的session就能得到保证了。
缺点:
1,在应用服务器集群中,如果有一台web服务器宕机或者重启,那么这台机器上的会话就会丢失,例如:如果会话中有用户的登录状态,那么用户再次发出请求,就会提示用户重新登录。
2,会话标识是应用层的信息,那么负载均衡设备要将同一个会话请求都保存到同一个web服务器上,就要进行应用层的解析,这个开销比在传输层大。
3,此时,负载均衡器变成了一个有状态的节点,要将会话保存到具体web服务器的映射,和无状态的节点相比,内存更大,容灾更麻烦。
如果做过数据库读写分离的都该知道,读写分离的时候,其实读的是从库,写的是主库,但是主库的信息会更新到从库,不考虑读写时间,我们可以任务从库和主库的数据是一致的,这个一致性主要靠同步来实现的。
在处理session的时候,我们同样可以采用这样的策略,在负载均衡设备上,无需动任何手脚,只进行无状态分发,反正分发到哪个服务器上,我之前的session都有,木事。
缺点:
1,同步session造成了网络带宽的开销,只要session数据有变化,就需要将数据同步到其他服务器上,机器越多,同步带来的网络开销就越大。
2,每台web服务器都要保存所有的session信息,如果整个集群的session数据很多,每台应用服务器就会保存非常多的session数据,严重占用内存。
既然嫌弃同步麻烦,那就把所有的session数据都拿出来,放到单独的地方,可以是单独数据库,或其他分布式存储系统,前面负载均衡器还是无状态转发,应用服务器每次读写session,都到相同的地方来取。
最近做的一个项目就是这个样子的,负载均衡用的是nginx,每次用户访问,都会产生一个sessionid,之后将session里面的信息序列化保存在redis库中,应用程序用到就通过我的redis访问模块来存取,会话完结之后,delete session。
缺点:
1,读写session数据引入了网络操作,这相对于本机的数据读取来说,问题就在于存在延时跟不稳定性,但是考虑到应用服务器跟session存储设备的通信均发生在内容,so,take it easy!
2,如果集中进行session存储,就要考虑到当session服务器发生问题的时候,会影响我们整个链条的使用。
如果不想引入额外节点来处理session,我们可以考虑将session数据,放在cookies中,在每次请求响应的时候都带着,每次服务器要读写session,只需从cookie中拿去来生成。
缺点:
1,cookies长度限制:因为cookie可以携带的数据长度是有限制的,所以,这同时也在一定程度上限制住了session的长度。
2,安全性:session数据本来都是服务器数据,而这个方案让session的数据到了外网及客户端上面,因此存在安全性问题,真实操作起来,需要对session进行加密处理。
3,带宽消耗
4,性能:每次http的请求跟响应都带有session数据,对web服务器来说,在同样的情况下,响应的结果输出越少,支持的并发请求越多。
小结:还是那句话,根据具体情况自己分析吧。