仿牛客社区开发(登录模块-会话管理)
概述
http无状态
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Overview
HTTP是无状态的:在同一个连接中,两个执行成功的请求之间是没有关系的。这就带来了一个问题,用户没有办法在同一个网站中进行连续的交互,比如在一个电商网站里,用户把某个商品加入到购物车,切换一个页面后再次添加了商品,这两次添加商品的请求之间没有关联,浏览器无法知道用户最终选择了哪些商品。而使用HTTP的头部扩展,HTTP Cookies就可以解决这个问题。把Cookies添加到头部中,创建一个会话让每次请求都能共享相同的上下文信息,达成相同的状态。
注意,HTTP本质是无状态的,使用Cookies可以创建有状态的会话。
http cookie
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies
HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的HTTP协议记录稳定的状态信息成为了可能。
cookie中只能存字符串和少量数据,因为cookie存在浏览器本地,浏览器只能识别java字符串类型,而且每次请求都携带cookie,故存少量数据,避免网络资源浪费
session
javaEE的标准,用于在服务端记录客户端信息,相比于cookie存放在客户端,存放在服务端的数据更加安全,但是也会增加服务端的压力
浏览器先服务端发起请求之后,服务器维护一个session,但是可能有多个浏览器访问服务器,为了使每个浏览器和服务器会话一 一对应,故有了session id,服务器创建一个session对象之后,返回一个这个session的唯一标识session id,返回给浏览器,浏览器创建cookie并携带session id存到浏览器本地,之后再发送请求时携带cookie,通过其中的session id找到对应会话
示例
cookie示例
设置cookie
浏览器发送 /cookie/set 请求,服务端设置cookie,并返回
服务端返回的response中带了cookie,之后cookie存到浏览器中
获取cookie
浏览器发送 /cookie/get 请求,因为设置了cookie生效返回在/community/alpha下,/cookie/get属于这个路径之下,故生效,浏览器所发的请求携带cookie
可以使用@CookieValue注解获取会话中的cookie
浏览器request请求头中携带了cookie
session示例
创建session对象
浏览器发起/session/set请求,服务端收到请求,创建session
服务端返回的response中携带cookie(session id)
获取session
服务端发起任何请求都携带cookie(session id),通过指定的session id获得服务端对应的session对象
浏览器请求中携带cookie(session id)
问题
分布式部署时,为什么不用session?
分布式中通过nginx做负载均衡(轮询,加权轮询,源地址哈希等),那么浏览器第一次发起请求,经过nignx,将该请求分发给服务器1处理,服务器1创建了对应浏览器的sesion对象。之后同一个浏览器再次发起请求时,根据负载均衡算法,比如轮询,可能会将请求分发到服务器2,但是服务器2中没有对应的session
解决思路:
- nignx使用源地址哈希算法做负载均衡,使同一个浏览器的请求都分发到指定服务器(违背了负载均衡的初衷,使请求均匀的分发到后方服务器)
- 服务器同步session(服务器之间进行关联,相互之间不那么独立了,而且服务间同步,会影响服务器性能)
- 将所有session放入一个服务器中去维护,其他服务器从共享session服务器获取session(该服务器是单体的,当初使用分布式方案解决性能瓶颈,现在该服务器是单体的,显然违背了初衷,如果构建该服务器的集群,则与思路2,也没区别了,服务器之间同步session,影响服务器性能)
- 用关系型数据库存session,做集群,主从备份(传统关系型数据库将数据存到硬盘中,那么磁盘IO,在并发量大时,可能会影响系统性能)
最终解决方案:
- 使用Nosql数据库redis存session(redis数据存内存,且单线程,读写操作快)