Session丢失的问题分析
一、问题描述:
1、在北京信息知识产权中心我们在他们没有完成的项目中发现一个问题就是,当一个用户登陆到一个webapp系统,正常操作一会或者当浏览器有返回404错误号码的时候就会出现用户的webapp有自动跳转到login页面。
二、问题分析
1、首先是确定问题所在:
当我测试的时候发现,在集群在会出现这样的问题,但是在单节点的weblogic server中不会发生这种情况,这样子我们先把问题定位到proxy上。所以我们有必要了解一下proxyserver。
2、Proxy的工作原理:
Proxy server是干什么的?
代理服务器是为集群提供负载平横和故障转移功能。
代理的连接过程:
当 HTTP 客户端请求 Servlet 时,HttpClusterServlet将该请求代理传输到 WebLogic Server 群集。HttpClusterServlet维护群集中所有服务器的列表以及访问群集时要使用的负载平衡逻辑。在上面的示例中,HttpClusterServlet将客户端请求路由到了 WebLogic Server A 承载的 Servlet。WebLogic Server A 成为了承载该客户端的 Servlet 会话的主服务器。为了对该 Servlet 提供故障转移服务,主服务器将客户端的 Servlet 会话状态复制到群集中的某个次级 WebLogic Server。这样可确保即使在主服务器失败(例如由于网络失败)时该会话状态的副本仍存在。在上面的示例中,服务器 B 被选择为次级服务器。
Servlet 页通过HttpClusterServlet返回到客户端,然后客户端浏览器收到指令,写入列出该 Servlet 会话状态主位置和次级位置的 Cookie。如果客户端浏览器不支持 Cookie,WebLogic Server 则可以使用 URL 重写来代替。
代理故障转移的过程:
如果主服务器失败,HttpClusterServlet就使用客户端的 Cookie 信息来确定承载会话状态副本的次级 WebLogic Server 的位置。HttpClusterServlet会自动将客户端的下一个 HTTP 请求重定向到次级服务器,故障转移对于客户端是透明的。
发生失败之后,WebLogic Server B 成为承载 Servlet 会话状态的主服务器,并且会创建新的次级服务器(在上面示例中为服务器 C)。在 HTTP 响应中,代理会更新客户端的 Cookie 来反映新的主服务器和次级服务器,以考虑后续故障转移的可能性。
在由两个服务器组成的群集中,客户端将以透明方式故障转移到承载次级会话状态的服务器。但是,客户端会话状态的复制不会继续,除非另一个 WebLogic Server 变为可用状态并加入该群集。例如,如果原始主服务器重新启动或重新连接网络,则会使用它来承载次级会话状态。
3.对于紫光项目中的session丢失的问题,在项目A中请求项目B中的内容,但是项目B还没有部署,项目中也没有对错误号码进行拦截并且跳转,当然在请求的时候会出现”404”错误,直接导致HttpClusterServlet在得到用户端错误的请求的时候会直接发送到后端的WebLogic Server上进行对资源的寻找,结果没有找到。返回就是一个404错误号码和cookies。这时候应用程序中也没有很好的处理好这样的错误。但是当我们再次返回到登录以后的页面时候,在次对其进行操作,这时候,cookies不是原来正确登陆以后的cookies了而是变成了报错后的cookies。所以会发生session丢失。
四、问题解决方法
1、对与这样的问题我们的处理办法是在proxy中直接指定项目名称,以方便HttpClusterServlet在遇到这样的事情的时候还能使用正确url地址,错误发生以前的cookies进行操作。这样HttpClusterServlet就不用在“/”下面一个一个的找,而是在url中的项目名称中指定的位置进行资源的寻找。这样即使是找不到资源也不会session丢失。
去掉原来的增加新的并且具体指定我们的项目名称。
<!--
<servlet-mapping>
<servlet-name>HttpClusterServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
-->
<!--
这个下面是一个具体的例子
-->
<servlet-mapping>
<servlet-name>HttpClusterServlet</servlet-name>
<url-pattern>/BookStore/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>HttpClusterServlet</servlet-name>
<url-pattern>/bs/*</url-pattern>
</servlet-mapping>