株洲网站制作建设,湖南网页设计培训网站建设,app自助平台制作,黑蜘蛛网站大家好#xff0c;我这名CRUD工程师又来了#xff0c;最近我的一个同事突然在看分布式Seesion的问题#xff0c;然后我们两个也是互相讨论了一下#xff0c;今天我就想着把分布式Session的知识点好好的梳理一下。
在很多系统中#xff0c;用户的登录功能都是用Session去实…大家好我这名CRUD工程师又来了最近我的一个同事突然在看分布式Seesion的问题然后我们两个也是互相讨论了一下今天我就想着把分布式Session的知识点好好的梳理一下。
在很多系统中用户的登录功能都是用Session去实现的客户端填写好用户名和密码发送一个请求服务器收到请求之后创建Session然后返回当前Session对应的一个JessionId浏览器存储在cookie中当客户端调用其他方法给服务器发送请求的时候就会携带JessionId服务端收到请求后验证Session是否存在进而判断用户是否登录。
在分布式环境下Session就会出现问题了假如服务端部署在两个服务器A和B上
用户登录时请求落在了服务器A上服务器A创建了一个Session并返回JessionId
用户获取个人信息时请求落在了服务器B上请求携带的JesssionId在服务器B上并不会找到对应的Session。
这时候服务器B就会给客户端返回一个异常提醒用户未登录客户端收到返回值用户就会发现自己又被T到登录界面了
接下来我们就看看在分布式环境下如何实现Session的一致性
一 、客户端存储
既然分布式环境中一个客户端的多个请求可能会落在多个服务器上那么我们是否可以改变策略直接将Session信息存储在客户端 答案当然是可以的服务器将Session信息直接存储到cookie中这样就保证了Session的一致性但是我们并不推荐这样去做这样就会产生数据安全的隐患因为将一些信息存储在cookie中相当于就把这些信息暴露给了客户端存在严重的安全隐患。
缺点
系统安全性存在问题cookie对于数据类型及数据大小有所限制
二 、Session复制
将服务器A的Session复制到服务器B同样将服务器B的Session也复制到服务器A这样两台服务器的Session就一致了。像tomcat等web容器都支持Session复制的功能在同一个局域网内一台服务器的Session会广播给其他服务器。
缺点
同一个网段内服务器太多每个服务器都会去复制session会造成服务器内存浪费。
三、Session黏性
利用Nginx服务器的反向代理将服务器A和服务器B进行代理然后采用ip_hash的负载策略将客户端和服务器进行绑定也就是说客户端A第一次访问的是服务器B那么第二次访问也必然是服务器B这样就不存在Session不一致的问题了。 缺点
如果服务器A宕机了那么客户端A和客户端B的Session就会出现丢失并且客户端A、B的所有请求都会失败
四、session集中管理
这种方式就是将所有服务器的Session进行统一管理可以使用redis等高性能服务器来集中管理Session而且spring官方提供的spirng-session就是这样处理Session的一致性问题。这也是目前很多企业开发用到的比较多的一种分布式Session解决方案。 spring-session实战
Spring提供了处理分布式Session的解决方案——Spring Session。Spring Session提供了用于管理用户会话的API和实现。
Spring Session提供了对redismongodbmysql等常用的存储库的支持Spring Session提供与HttpSession的透明整合这意味着开发人员可以使用Spring Session支持的实现切换HttpSession实现。
我在网上找了一个Spring Session 实现的流程图 Spring Session添加了一个SessionRepositoryFilter的过滤器用来修改包装请求和响应包装后的请求为SessionRepositoryRequestWrapper调用getSession()方法的时候实际上就是调用Spring Session实现了的Session。
Spring Session使用非常简单添加了相关依赖后直接操作HttpSession就可以实现效果。 pom.xml dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependencydependencygroupIdorg.springframework.session/groupIdartifactIdspring-session-data-redis/artifactId/dependencyyml spring:session:# session 失效时间分钟timeout: 86400# session 使用redis存储 store-type: redis# redis 配置redis:# redis 端口号port: 6379# redis 服务器地址host: localhost# redis库database: 0# redis 密码password: 123456使用session public String test( HttpServletRequest request){HttpSession session request.getSession();session.setAttribute(key_big_handsome,value:it is me);return session.getAttribute(key_big_handsome).toString();
}执行了这个方法我们看redis
第一个用来表示Session在Redis中的过期这个k-v不存储任何有用数据只是表示Session过期而设置。这个key在Redis中的过期时间即为Session的过期时间间隔。第二个存储这个Session的id是一个Set类型的Redis数据结构。这个key中的最后的1681633260000值是一个时间戳根据这个Session过期时刻滚动至下一分钟而计算得出。第三个用来存储Session的详细信息包括Session的过期时间间隔、最近的访问时间、attributes等等。
Spring Session中有个定时任务每个整分钟都会查询相应的spring:session:expirations:整分钟的时间戳中的过期SessionId然后再访问一次这个SessionId即spring:session:sessions:expires:SessionId以便能够让Redis及时的产生key过期事件——即Session过期事件。