实现Session共享多种解决方案

Session共享

为什么会有session共享

  1. 目前互联网公司的项目大多是在微服务华和分布式的环境中进行搭建的,这就会导致一个项目很有可能分布部署在几个甚至很多的服务器集群下,此时就会出现一个问题
  2. 当用户进行一个session会话时,比如一个用户去登录项目,一般的大公司的项目都是有Nginx进行反向代理的,在此简单举例一下Nginx常用的几种反向代理的策略: 1.轮询策略 , 2.权重比例策略 , 3.ip_hash策略 , 4. 还可以自定义的策略 , 在Nginx的反向代理下,一般会把用户的请求分发到不同的服务器上,但是如果用户的请求存放在该服务器A上,那么该用户的sessionID 就存储在该服务器上JVM的一个ConcurrentHashmap中,以sessionID为key.
  3. 但如果此时用户请求的一个服务模块可能需要调用到服务器B,当用户发起请求的时候,此时的服务器B上并没有存储该用户的sessionID, 所有就会再次让用户进行一个登录操作,还有可能会导致用户本来就想单纯的完成一个下单操作,但却登录了好几次的清空
  4. 所有session共享方案在分布式环境中和微服务系统下,显得额外重要

解决方案一 基于Nginx的Ip_hash负载均衡

  • 就是把请求过来的ip地址对你的多台可用的服务器进行取模,然后把你的请求通过Nginx的反向代理给分发到对应的服务器上.

这里会把可用的服务器放到一个数组当中,如果取模得到的结果是几,就会把请求分到服务器数组的下标中为几的服务器上

具体实现

  • 需要在Nginx.conf文件中进行对应的修改, 添加自己可用的服务器
upstream zx.com {
		ip_hash;
        server localhost:8081 weight=1;
        server localhost:8082 weight=2;
        server localhost:8083 weight=3;
        server localhost:8084 weight=4;
        server localhost:8085 backup;
        server localhost:8086 backup;
    }

    server {
        listen       8088;
        server_name  localhost;
}

优点:

  • 配置简单,对应用无侵入性,不需要修改代码
  • 只要hash属性均匀的,多台web-server的负载是均衡的
  • 便于服务器水平扩展
  • 安全性较高

缺点

  • 服务器重启会造成部分session丢失
  • 水平扩展中也会造成部分session丢失
  • 存在单点负载高的风险

解决方案二: 基于Tomcat的session复制

  • 该解决方案就是当用户请求的时候,把产生的sessionID复制到系统所有的服务器中,这样就能保证当前用户请求的时候从服务器A可能调用到服务器B的时候,也能保证服务器B也能有该用户的sessionID ,这样也就解决了

具体实现

  1. 修改server.xml中的Cluster节点;
  2. 修改应用web.xml,增加节点: <distribtable/>

优点:

  • 配置简单,对应用无侵入性,不需要修改代码
  • 能适应各种负载均衡策略
  • 服务器重启或宕机不会造成session丢失
  • 安全性较高

缺点

  • session同步会有一定的延迟
  • 占用内网宽带资源
  • 受限于内存资源,水平扩展能力差
  • 服务器数量就多
  • 序列化反序列化消耗CPU性能

解决方案三: 使用Redis做缓存session的统一缓存

  • 该方法就是把每次用户的请求的时生成的sessionID存放到Redis的服务器上.在基于Redis的特性进行设置一个失效时间的机制,这样就能保证用户在我们设置的Redis中的session失效时间内,都不需要进行再次登录

具体实现

一. SpringBoot下基于Cookie实现的SpringSession
  1. 导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>No10_Session</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>2.7.17</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
<!--        Redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        
<!--        SessionRedis -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
    </dependencies>

</project>
  1. 书写配置文件
server:
  port: 8081
  servlet:
    context-path: /

spring:
  redis:
    host: 192.168.230.190
    port: 6379
    password: 123456
  1. 为项目启动类添加注解启用Spring-session
@SpringBootApplication
@EnableRedisHttpSession
public class GlobalSessionApplication {
	public static void main(String[] args) {
		SpringApplication.run(GlobalSessionApplication.class, args);
	}
}
  1. 为项目添加控制类
@RestController
public class SessionController {

    @Value("${server.port}")
    private Integer pore;

    @GetMapping("/set")
    public String set (HttpSession session){
        session.setAttribute("user","张三");
        return String.valueOf(pore);
    }

    @GetMapping("/get")
    public String get (HttpSession session){
        return "user: "+session.getAttribute("user")+" \n 端口号: "+pore;
    }
}
  1. 启动项目并查看Redis中的值
    启动项目时配置端口号
    请添加图片描述
    存储数据的查看
    请添加图片描述

  2. 在上述操作中已经完成了session共享但是会发现Redis中的数据出现了乱码的情况 这是因为默认采用的的是JDK序列化方式存储的,可读性比较差,隐藏我们可以补充添加Spring序列化方法

public class SessionConfig {

    @Bean
    public RedisSerializer springSessionDefaultRedisSerializer(){

        return new GenericJackson2JsonRedisSerializer();
    }

    @Bean
    public CookieSerializer cookieSerializer(){
        DefaultCookieSerializer defaultCookieSerializer = new DefaultCookieSerializer();
        defaultCookieSerializer.setCookiePath("/"); //解决contextPath不同的问题
//       设置cookie 的一级域名,不设置时默认与url中的域名一致
//        cookieSerializer.setSameSite(null); //解决axios跨域携带cookie无效问题
        return defaultCookieSerializer;
    }
}

这样整个问题就解决了!!!

Redis中的存储说明:

  1. spring:session 是默认的Redis HttpSession 前缀(redis中,我们常用’ : ’ 作为分割符).
  2. 每一个session都会创建3组数据
  • hash结构, spring-session存储的主要内容
    spring:session:sessions:709261a8-8c40-4097-8df2-92f88447063f
    hash结构有key和field,如上面的例子:hash的key为"spring:session:sessions"前缀加709261a8-8c40-4097-8df2-92f88447063f,该key下的field有:

    • key=sessionAttr:user, value=“张三” // session存储数据内容

    • key=creationTime, value=1644302828502 //创建时间(采用毫秒数保存)

    • key=maxInactiveInterval, value=1800 //最大非活动间隔(默认1800秒,即30分钟)

    • key=lastAccessedTime, value=1644302833137 //最后访问时间(采用毫秒数保存)

      当我们重新访问localhost:8082/get时,我们可以看到lastAccessedTime会发生改变。

  • String结构,用于ttl过期时间记录
    spring:session:sessions:expires:70924e71-c540-4097-8df2-92f88447063f key为“spring:session:sessions:expires:”前缀+70924e71-c540-4097-8df2-92f88447063fvalue为空

  • set结构,过期时间记录
    spring:session:expirations:16443046000000
    set的key固定为“spring:session:expirations:16443046000000”set的集合values为:

    • expires:c7fc28d7-5ae2-4077-bff2-5b2df6de11d8 //(一个会话一条)

简单提一下:redis清除过期key的行为是一个异步行为且是一个低优先级的行为,用文档中的原话来说便是,可能会导致session不被清除。于是引入了专门的expiresKey,来专门负责session的清除,包括我们自己在使用redis时也需要关注这一点。在开发层面,我们仅仅需要关注第一组hash结构数据就行了。

二. SpringBoot下基于Token实现的SpringSession
  1. 修改配置类
@Bean
public HeaderHttpSessionIdResolver headerHttpSessionIdResolver(){
	return new HeaderHttpSessionIdResolver("token");
}
  1. 书写配置文件
spring:
  session:
    store-type: redis
  1. 在跨域条件下配置同源策略
@Configuration
public class CorsConfig implements WebMvcConfigurer {
	@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**")
		.allowedHeaders("*")
		.allowedMethods("*")
		.allowedOrigins("*")
		.exposedHeaders("token");
	}
}


解决方案四: Session存放到Cookie

把session放到cookie中去,因为每次用户请求的时候,都会把自己的cookie放到请求中,所以这样就能保证每次用户请求的时候都能保证用户在分布式环境下,也不会在进行二次登陆。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
更新日志:*更新了不能注册 *更新了增加新成员提示数据库错误,睡死猪OA办公系统,以asp开发的OA类办公软件系统。 1 、 COOKIES 、 SESSION 二种记录用户资料方式,使不支持 COOKIESE 的浏览器自动选择 SESSION 方式记录用户资料 2 、免费、开源,非凡的访问速度和强大的负载能力。睡死猪工作室网络办公系统一直坚持免费+开源的策略,依靠优质的服务,采用国际通用的项目管理方法,模块化、高效统一的内核编写模式 3 、周密的安全部署和攻击防护。独创的用户登录机制保持用户不同地点的安全登录,对各种不同浏览方式的识别并给予不同的安全防护和处理,对全局运行日志的把握和管理让您随时掌握论坛的运行情况。 4 、无需独立服务器,有个虚拟空间就可以快速建立企业信息中枢 5 、客户端无需安装专用软件,使用浏览器即可实现全球办公 6 、支持部门 / 成员单位模式,全面面向企事业单位应用 7 、方便挂接外部的 B/S 系统,具有良好的扩展性 8 、集成 WEBSMS 即时通讯工具,实现类似企业 QQ 的即时通讯 9 、集成 Internet 邮件管理组件,提供 web 方式的远程邮件服务 10 、集成网络硬盘组件,提供便捷的局域网、广域网文件共享方案 11 、集成商业管理组件,轻松的管理客户、供应商资料和产品销售记录 12 、集成内部邮件、即时短信、聊天室、论坛等模块,提供企业内部信息交流的多种方式 13 、集成考勤管理、员工日程安排查询、会议管理、车辆管理等模块,提供企业管理者全新的管理工具 特别注意: 这个不是程序的错误,是windows2003系统的限制。 解决办法是: 1.关闭IIS Admin Service服务 2.更改C:WINDOWSsystem32inetsrv目录下的MetaBase.xml 文件,将第601行的AspMaxRequestEntityAllowed=204800.更改为AspMaxRequestEntityAllowed=5120000(5120000是你要设置的最大大小) 3.保存文件.重启IIS Admin Service服务, 特别提示: 1、本地测试请使用windows2003、完整的IIS6.0以上。 2、整站程序请上传至虚拟主机根目录下。 3、整站程序绝对无功能限制,完全开放免费使用。请不要再反复咨询这个问题了。 员工测试帐号密码test 管理员测试帐号admin密码admin888
JeeSpringCloud是一个基于SpringBoot2.0的后台权限管理系统,界面简洁美观敏捷开发系统架构。核心技术采用Spring、MyBatis、Shiro没有任何其它重度依赖。 互联网云快速开发框架,微服务分布式代码生成的敏捷开发系统架构。项目代码简洁,注释丰富,上手容易,还同时集中分布式、微服务,同时包含许多基础模块和监控、服务模块。模块包括:定时任务调度、服务器监控、平台监控、平台设置、开发平台、单点登录、Redis分布式高速缓存、会员、营销、在线用户、日志、在线人数、访问次数、调用次数、直接集群、接口文档、生成模块、代码实例、安装视频、教程文档 代码生成(单表、主附表、树表、列表和表单、redis高速缓存对接代码、图表统计、地图统计、vue.js)、dubbo、springCloud、SpringBoot、mybatis、springspringmvc。 功能 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 岗位管理:配置系统用户所属担任职务。 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 参数管理:对系统动态配置常用参数。 通知公告:系统通知公告信息发布维护。 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 登录日志:系统登录日志记录查询包含登录异常。 在线用户:当前系统中活跃用户状态监控。 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 代码生成:前后端代码生成(单表、主附表、树表、列表和表单、增删改查云接口、redis高速缓存对接代码、图表统计、地图统计、vue.js) ,并生成菜单和权限直接使用。 系统接口:根据业务代码自动生成相关的api接口文档。 连接池监视:监视当期系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 在线接口文档:使用swager生成在线文档。 ActiveMQ队列:提供ActiveMQ队列,处理批量发送大数据量邮件、大数据量日志文件。 工作流:功能包括在线办公、我的任务、审批测试、流程管理、模型管理。 CMS:功能包括内容管理、内容管理、统计分析、栏目设置、首页。 dubbo:代码生成直接生成dubbo对接代码。 服务器Down机邮件监控:通过定时任务监控服务器是否Down机,并发送通知邮件。 服务器监控:通过sigar进行服务器图形化监控。 异常邮件监控:全局拦截系统异常,并发送通知邮件。 单点登录:使用shior和Redis共享session方式实现单点登录。 Redis分布式高速缓存:代码生成直接生成Redis对接代码。 特性: JeeSpringCloud基于SpringBoot+SpringMVC+Mybatis+Redis+SpringCloud+Vue.js微服务分布式代码生成的敏捷开发系统架构。项目代码简洁,注释丰富,上手容易,还同时集中分布式、微服务,同时包含许多基础模块(用户管理,角色管理,部门管理,字典管理等10个模块。成为大众认同、大众参与、成就大众、大众分享的开发平台。JeeSpring官方qq群(328910546)。代码生成前端界面、底层代码(spring mvc、mybatis、Spring bootSpring Cloud、微服务的生成)、安全框架、视图框架、服务端验证、任务调度、持久层框架、数据库连接池、缓存框架、日志管理、IM等核心技术。努力用心为大中小型企业打造全方位J2EE企业级平台ORM/Redis/Service仓库开发解决方案。一个RepositoryService仓库就直接实现dubbo、微服务、基础服务器对接接口和实现。 努力用心为大中小型企业打造全方位J2EE企业级平台开发解决方案Spring Boot/Spring cloud微服务是利用云平台开发企业应用程序的最新技术,它是小型、轻量和过程驱动的组件。微服务适合设计可扩展、易于维护的应用程序。它可以使开发更容易,还能使资源得到最佳利用。 微服务/集群(nignx) 支持REST风格远程调用(HTTP + JSON/XML):基于非常成熟的Spring Boot框架,在Spring Boot Spring Cloud中实现了REST风格(HTTP + JSON/XML)的远程调用,以显着简化企业内部的跨语言交互,同时显着简化企业对外的Open API、无线API甚至AJAX服务端等等的开发。 事实上,这个REST调用也使得Dubbo可以对当今特别流行的“微服务”架构提供基础性支持。 另外,REST调用也达到了比较高的性能,在基准测试下,HTTP + JSON默认的RPC协议(即TCP + Hessian2二进制序列化)之间只有1.5倍左右的差距,详见下文的基准测试报告。 ORM/Redis/Service仓库 RepositoryORM仓库,提供ORM接口和多种实现,可进行配置实现。 RepositoryRedis仓库,提供Redis接口和多种实现,可进行配置实现。可以配置调用单机、redis、云redis对接。 RepositoryService仓库,提供Service接口和多种实现,可进行配置实现。一个RepositoryService仓库就直接实现dubbo、微服务、基础服务器对接接口和实现
Redis可以通过将session信息存储在Redis数据库中来实现session共享。这种方式的优点是可以让服务器之间共享session信息,从而避免用户的请求需要重复认证。同时,使用Redis作为session存储介质可以提供更好的性能和可靠性。引用将session存储在Redis中可以确保session的持久性,即使服务器重启或者宕机,用户的session信息也不会丢失。另外,通过将session信息存储在Redis中,可以方便地进行session的管理和跨服务器的共享。在配置上,需要在应用的配置文件中指定Redis的连接信息以及相关的session配置,如连接的端口号、主机地址、数据库等。引用通过这种方式,可以实现基于Redissession共享功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Redis入门-4-Redis实现session共享](https://blog.csdn.net/a1216701075/article/details/88970820)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [session共享redis实现)](https://blog.csdn.net/YXXXYX/article/details/125342292)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值