大型网站分布式架构(九)—— 从Cookie机制到会话Session再到集群中Session的场景

xiaoxiao2021-03-01  35

目录大型网站分布式架构(一)—— SpringBoot构建项目大型网站分布式架构(二)—— Linux下Tomcat的安装和项目部署大型网站分布式架构(三)—— 使用Apache Bench进行压力测试大型网站分布式架构(四)—— JVisualVM远程监控Tomcat大型网站分布式架构(五)—— Apache Bench与JVisualVM联调大型网站分布式架构(六)—— Nginx的安装大型网站分布式架构(七)—— Nginx整合Tomcat实现动静分离大型网站分布式架构(八)—— Tomcat集群横向拓展 + Nginx负载均衡 大型网站分布式架构(九)—— 从Cookie机制到会话Session再到集群中Session的场景大型网站分布式架构(十)—— Springboot + SpringSession + Redis实现Tomcat集群Session共享大型网站分布式架构(十一)—— Keepalived+Nginx+Tomcat集群实现服务的高可用HA

Cookie机制

cookie是浏览器用来存储少量数据的一种机制,数据以”key/value“形式存储,浏览器发送http请求时自动附带cookie信息

Session会话机制

HTTP请求是无状态的,即HTTP协议并不能识别出上一个HTTP请求和下一个HTTP请求是否来自同一个用户可以通过维持一个会话来判定用户:浏览器第一次请求服务器,服务器创建一个会话,并将会话的id作为响应的一部分发送给浏览器,浏览器存储会话id,并在后续第二次和第三次请求中带上会话id,服务器取得请求中的会话id就知道是不是同一个用户了但是每次请求都携带会话id显然不靠谱,这时就可以通过cookie机制就实践会话id的传递

Tomcat下的Cookie和HttpServletSession

浏览器第一次访问Tomcat时,Tomcat会创建一个HttpServletSession会话对象,同时创建一个名为JSESSIONID的Cookie对象,该cookie存储着当前HttpServletSession会话对象的id,可以通过这个id找到当前会话,从而实现了用户状态的保持。而Session对象存活时间默认等于30分钟或者浏览器的打开时间,在这段时间内,我们可以获取Session对象中存储的任何信息。这就是Tomcat下Cookie和Session机制

更新项目操作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>

部署项目到Tomcat集群

[root@centos6-1 webapps]# rz rz waiting to receive. Starting zmodem transfer. Press Ctrl+C to cancel. Transferring appdemo.war... appdemo.war was skipped [root@centos6-1 webapps]# scp -r appdemo.war root@centos6-2:$PWD appdemo.war 100% 17MB 16.9MB/s 00:00 [root@centos6-1 webapps]# scp -r appdemo.war root@centos6-3:$PWD appdemo.war 100% 17MB 16.9MB/s 00:00 [root@centos6-1 webapps]#

启动Tomcat集群

[root@centos6-1 bin]# ./startup.sh [root@centos6-2 bin]# ./startup.sh [root@centos6-3 bin]# ./startup.sh

浏览器访问Nginx

上一章讲到的Nginx集成Tomcat集群:大型网站分布式架构(八)—— Tomcat集群横向拓展 + Nginx负载均衡

1.直接访问Nginx:192.168.214.150/appdemo/

因为是初次访问,session中并未设置random值,所以取不到值

2.携带random参数访问:192.168.214.150/appdemo/?random=zaomianbao

发现random存入了session中,而此时处理这个请求的Tomcat是在centos6-1上的Tomcat1

3.连续直接访问Nginx:192.168.214.150/appdemo/

发现我们之前存入session中的random的值没有了,而博主并没有关闭浏览器,且是在连续请求的情况下,session也不可能过期。就连当请求分配给Tomcat1处理时也取不到random的值。

Session去哪了

其道理很简单:

当第一次打开浏览器请求并携带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的共享

转载请注明原文地址: https://www.6miu.com/read-4200348.html

最新回复(0)