浏览器第一次访问Tomcat时,Tomcat会创建一个HttpServletSession会话对象,同时创建一个名为JSESSIONID的Cookie对象,该cookie存储着当前HttpServletSession会话对象的id,可以通过这个id找到当前会话,从而实现了用户状态的保持。而Session对象存活时间默认等于30分钟或者浏览器的打开时间,在这段时间内,我们可以获取Session对象中存储的任何信息。这就是Tomcat下Cookie和Session机制
修改IndexController如下:
package com.zaomianbao.appdemo; import org.springframework.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Date; @Controller public class IndexController { @RequestMapping("/") public String index(HttpServletRequest request){ try { System.out.println(new Date()); InetAddress addr = InetAddress.getLocalHost(); String ip=addr.getHostAddress().toString(); //获取本机ip String host=addr.getHostName().toString(); //获取本机计算机名称 System.out.println(ip + " " + host); request.setAttribute("ip",ip); request.setAttribute("host",host); HttpSession session = request.getSession(); String random = request.getParameter("random"); if(StringUtils.hasText(random)){ session.setAttribute("random",random); } } catch (UnknownHostException e) { e.printStackTrace(); } return "index"; } }修改index.html如下
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>欢迎进入枣面包的面包坊</title> <script type="text/javascript" src="js/nothing.js"></script> </head> <body> <h1>欢迎进入枣面包的面包坊</h1> <img src="img/photo.jpg"><br/> 主机名:<span th:text="${host}" ></span><br/> ip:<span th:text="${ip}" ></span><br/> session中的random值:<span th:text="${session.random}" ></span> </body> </html>上一章讲到的Nginx集成Tomcat集群:大型网站分布式架构(八)—— Tomcat集群横向拓展 + Nginx负载均衡
因为是初次访问,session中并未设置random值,所以取不到值
发现random存入了session中,而此时处理这个请求的Tomcat是在centos6-1上的Tomcat1
发现我们之前存入session中的random的值没有了,而博主并没有关闭浏览器,且是在连续请求的情况下,session也不可能过期。就连当请求分配给Tomcat1处理时也取不到random的值。
其道理很简单:
当第一次打开浏览器请求并携带random参数时,请求分配给了Tomcat1,因为是第一次请求,这时Tomcat1响应回来时创建了名为JSESSIONID的cookie并携带回来给了浏览器当浏览器连续第二次请求时,请求分给Tomcat2处理了,并且携带那个JSESSIONID的cookie给了Tomcat2,不管此时是否携带random参数,当在接口请求响应回来时,Tomcat2发现从名为JESESSIONID的cookie中获得的会话id并不能找到对应的HttpSession对象,所以Tomcat2重新创建了一个HttpSession,并将新的会话id放入名为JESESSION的cookie中返回给了浏览器当浏览器连续第二次请求时,请求又分给Tomcat3处理了,又识别不了,又重新创建,又产生新的会话id返回给浏览器,不断重复此操作。所以,问题在于Tomcat找不到Session对象,因为Session对象都存放在各自的Tomcat容器中,所以集群中的3台Tomcat容器找不到会话id对应的会话Session对象。所以得出结论:因为集群没有共享Session,所以导致会话的不断刷新,从而不能保持会话的状态。
之前的Nginx+Tomcat集群的架构解决了高并发的问题,但又带来了Session会话状态的问题。下一章博主将通过使用Redis实现集群中的Session的共享