一、HTTP的基本性质
- 简单的
- 可扩展的
- 无状态,有会话
无状态:两个执行成功的请求之间没有关系,因此用户没有办法在同一个网站进行连续的交互。
HTTP Cookies可以解决这个问题:把Cookie添加到头部,创建一个会话让每次请求都能共享相同的信息,达到相同的状态。
HTTP本质是无状态的,使用Cookies可以创建有状态的会话。
二、Cookie
是服务器发送给浏览器,并保存在浏览器的一块数据。
浏览器下次访问改服务器时,会自动携带该块数据,将其发送给服务器。
创建cookie
@RequestMapping(path = "/cookie/set", method = RequestMethod.GET)
@ResponseBody
public String setCookie(HttpServletResponse response) {
// 创建cookie
Cookie cookie = new Cookie("code", CommunityUtil.generateUUID());
// 设置cookie生效的范围:指定访问的哪些路径会发送cookie,不需要的就不会发送cookie
// 在该路径和子路径下有效
cookie.setPath("/community/alpha");
// 设置cookie的生存时间
cookie.setMaxAge(60 * 10);
// 发送cookie
response.addCookie(cookie);
return "set cookie";
}
获取cookie
@RequestMapping(path = "/cookie/get", method = RequestMethod.GET)
@ResponseBody
public String getCookie(@CookieValue("code") String code) {
System.out.println(code);
return "get cookie";
}
三、Session
cookie的数据是存储在客户端的,每次访问服务器都会增加流量。
session是JavaEE的标准,用于在服务端记录客户端信息。
数据存放在服务端更安全,但是也会增加服务端的内存压力。
// session示例
@RequestMapping(path = "/session/set", method = RequestMethod.GET)
@ResponseBody
public String setSession(HttpSession session) {
session.setAttribute("id", 1);
session.setAttribute("name", "Test");
return "set session";
}
@RequestMapping(path = "/session/get", method = RequestMethod.GET)
@ResponseBody
public String getSession(HttpSession session) {
System.out.println(session.getAttribute("id"));
System.out.println(session.getAttribute("name"));
return "get session";
}
四、分布式情况下的session
1.原因
客户端发送一个请求,经过负载均衡后,改请求会被分配到服务器中的其中一个,由于不同服务器内嵌不同的web服务器(例如Tomcat),不同的web服务器中并不能发现之前web服务器保存的session信息,就会在此生成一个JSESSIONID,之前的状态就会丢失。
2.解决方案
方案一:
设置负载均衡分配策略为粘性session:只要是同一个sessionID,就分配给同一个服务器处理。
问题:无法保证服务器的负载均衡
方案二:
同步session:当某个服务器创建session后,会同步给其他服务器
问题:性能低,耦合性高
方案三:
共享session:用一个单独的服务器只存session,其他服务器通过其获取session
问题:单独的服务器挂了,整体就用不了了。
方案三改进:
基于Redis存储session:大部分数据能存cookie就存cookie,某些敏感的数据存到Redis中,Redis可做主从同步(较为成熟)