当服务器的访问压力达到一定程度时,会采用分布式部署方案,即分布式集群部署,多个服务节点都可以提供同样的服务能力,这样,当大量的http请求到达服务端时,由负载均衡算法,将不同的请求相对均匀地分发到不同的服务节点上,达到了降低单个服务节点的访问压力,同时也可以解决服务单点故障问题。
采用分布式集群部署方案,一般都要解决session共享问题,如下图所示:
考虑问题:同一个client依次发送3个http请求,顺序依次是request1,request2,request3,经负载均衡算法,被分发到3个不同的服务节点node1,node2,node3,那么,client首先访问server node1进行登录操作,登录成功后创建session,server node1上保存session,同时执行response.addCookie(sessionId)返回给client,client保存cookie;然后client发起请求request2,此时request2访问到server node2,在server node2上根据sessionId找不到session,会提示session不存在,即server node1和 server node2无法共享同一个session...
那么如何让不同的server node共享session呢?
如下图所示:
设计需要思想:需要一个分布式cache(redis、memcached等),然后server node在创建session时,将session存入到分布式cache中,获取session时,从分布式session中取,这样就实现session共享了...
设计思想了解后,那么接下来就是实现方案了...
如下图所示:
我们只要做一件事,就是将session相关的操作访问我们自定义的方法,我们自定义的方法操作的是分布式cache,那么就可以解决session共享问题了,也就是下图所示:
首先,我们自定义HttpServletRequestWrapperConcrete、HttpSessionWrapper两个类,分别继承HttpServletRequestWrapper、HttpSession,然后对getSession(...)、getAttribute(name)、setAttribute(name,value)这些常用的方法进行override(重写),这样,原本访问HttpServletRequestWrapper、HttpSession的方法就可以访问我们自定义的HttpServletRequestWrapperConcrete、HttpSessionWrapper中相应的方法了,因此,开发人员就可以使用之前的调用方式一样进行操作了...
接下来就是访问的问题了,看下图:
如何将HttpServletRequest对象变成我们自定义的HttpServletRequestWrapperConcrete对象呢?以及将HttpSession对象变成HttpSessionWrapper对象呢?
对于1,将HttpServletRequest变成HttpServletRequestWrapperConcrete的问题,可以用Filter来实现:
对于2,将HttpSession变成HttpSessionWrapper的问题,实现方式是将HttpSession作为HttpServletRequestWrapperConcrete的成员变量,然后当HttpServletRequestWrapperConcrete的对象request创建session的时候,将执行request.session = new HttpSessionWrapper(...),这样访问的问题就解决了...
下面,给出实现流程...
至此,整个分布式session的实现方案结束...