• 自动秒收录
  • 软件:1973
  • 资讯:56783|
  • 收录网站:206633|

IT精英团

你还不明白分布式会话怎么解决?就看这个吧!

你还不明白分布式会话怎么解决?就看这个吧!

浏览次数:
评论次数:
编辑: 景同
信息来源: ITPUB
更新日期: 2022-06-17 21:00:59
摘要

平常做的项目都是在一台应用系统,并且所有的操作都在一台Tomcat服务器上,并不会引发Session共享的问题,所以并不会对我们的系统产生影响,但是当我们部署多个微服务的时候,再搭配Nginx进行负载

  • 正文开始
  • 相关阅读
  • 推荐作品

平时的项目都在一个应用系统里,所有操作都在一个Tomcat服务器上,不会造成会话共享的问题,所以不会影响我们的系统。但是,当我们部署多个微服务,使用Nginx进行负载均衡时,如果不处理分布式会话问题,当我们访问系统中的不同功能时,用户会频繁登录。

图形分析原因:

前提:图中的用户登录功能、商品订购模块、抢购模块属于独立的微服务模块。

当用户成功登录后想要访问图中另外两个模块的功能时,由于Nginx使用了默认的负载均衡策略(轮询),请求会按照时间顺序一个一个的分发到后端应用。也就是说,用户在Tomcat1上登录成功后,用户的信息放在Tomcat1的Session中。过了一会儿,用户想进行秒杀活动的功能操作。Nginx将请求分发到Tomcat2,但是此时Tomcat2的会话中没有用户信息,因此要求用户重新登录。在微服务分布式项目中,不同的功能模块将被划分到各自的微服务中。如果您需要再次登录才能访问某个功能,用户的体验将会大打折扣!

如何解决分布式会话问题?

一、解决方案列举

1. Session复制

优点:

不需要修改代码,只需修改Tomcat配置缺点:.

会话同步传输占用内网宽带

多个Tomcat的同步性能呈指数级下降。

会话占用内存,不能有效地水平扩展。

2. 前端存储

优点:

不占用服务器内存的缺点:

存在安全隐患。

数据大小受cookie限制。

占用外网宽带

3. Session粘滞

优点:

不需要修改代码。

服务器可以水平扩展。

缺点:

添加新机器将重新散列,导致重新登录。

应用程序重启后,您需要再次登录。

4. 后端集中存储

优点:

安全的

易于水平扩展

优点:

增加复杂性

代码需要修改。

二、Java代码实现解决分布式Session

1. SpringSession - Redis解决分布式Session

添加依赖关系

!-雷迪斯-

属国

groupIdorg.springframework.boot/groupId

artifactId spring-boot-starter-data-redis/artifactId

/依赖关系

!- commons-pools2对象池依赖项-

属国

groupId org . Apache.commons/groupId

artifactId commons-pool 2/artifactId

/依赖关系

!-春季会话依赖,微信官方账号:精选Java-

属国

groupIdorg.springframework.session/groupId

artifactIdspring-

session-data-redis</artifactId>
</dependency>

添加Redis配置

## Redis配置
spring:
  redis:
    # 服务器地址
    host: localhost
    # 端口
    port: 6379
    # 数据库
    database: 
    # 超时时间
    connect-timeout: 10000ms
    lettuce:
      pool:
        # 最大连接数
        max-active: 8
        # 最大连接阻塞等待时间 默认 -1
        max-wait: 10000ms
        # 最大空闲时间 默认8
        max-idle: 200
        # 最小空闲连接 默认8
        min-idle: 5

业务逻辑实现

/**
 * 登录功能
 * @param loginVo
 * @return
 */
@Override
public RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) {

    String username = loginVo.getUserName();
    String password = loginVo.getPassword();

    User user = userMapper.selectByUserName(username);
    if (user == null){
        throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
    }
    //判断密码是否正确
    if (!MDUtils.formPassToDBPass(password,user.getSalt()).equals(user.getPassword())){
        throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
    }
    //使用UUID生成字符串代替Cookie
    String ticket = UUIDUtil.uuid();
    request.getSession().setAttribute(ticket,user);
    CookieUtil.setCookie(request,response,"userTicket",ticket);
    return RespBean.success();
}

视图控制层

/**
 * 跳转商品列表
 * @param session
 * @param model
 * @return
 */
@RequestMapping("/toList")
public String toList(HttpSession session, Model model,@CookieValue("userTicket")String ticket){
    if (StringUtils.isEmpty(ticket)){
        return "login";
    }
    User user = (User) session.getAttribute(ticket);
    if (user == null){
        return "login";
    }
    model.addAttribute("user",user);
    return "goodsList";
}

登录测试

打开Redis管理软件发现Session信息已经添加到Redis中了

2. Redis解决分布式Session

导入依赖

<!--Redis-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--commons-pools2 对象池依赖-->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-pool2</artifactId>
</dependency>

Redis配置参考 【SpringSession - Redis解决分布式Session】

业务逻辑层

@Override
public RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) {

    String username = loginVo.getUserName();
    String password = loginVo.getPassword();

    User user = userMapper.selectByUserName(username);
    if (user == null){
        throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
    }
    //判断密码是否正确
    if (!MDUtils.formPassToDBPass(password,user.getSalt()).equals(user.getPassword())){
        throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
    }
    //成功Cookie
    String ticket = UUIDUtil.uuid();
    //将用户信息存入到redis中
    redisTemplate.opsForValue().set("userTicket",ticket);
    redisTemplate.opsForValue().set("user:"+ticket,user);
    //request.getSession().setAttribute(ticket,user);
    CookieUtil.setCookie(request,response,"userTicket",ticket);
    return RespBean.success();
}

/**
 * 根据cookie获取cookie
 * @param ticket
 * @return
 */
@Override
public User getUserByByCookie(String ticket,HttpServletRequest request,HttpServletResponse response) {
    if (StringUtils.isEmpty(ticket)){
        return null;
    }
    User user = (User) redisTemplate.opsForValue().get("user:" + ticket);
    if (user == null){
        CookieUtil.setCookie(request,response,"userTicket",ticket);
    }
    return user;
}

视图控制层

/**
 * 跳转商品列表
 * @param session
 * @param model
 * @return
 */
@RequestMapping("/toList")
public String toList(HttpSession session, Model model,HttpServletRequest request,HttpServletResponse response){
    String ticket = (String) redisTemplate.opsForValue().get("userTicket");
    if (StringUtils.isEmpty(ticket)){
        return "login";
    }
    //User user = (User) session.getAttribute(ticket);
    User user = userService.getUserByByCookie(ticket, request, response);
    if (user == null){
        return "login";
    }
    model.addAttribute("user",user);
    return "goodsList";
}

测试成功

查看Redis管理工具

vivo集装箱集群监控系统的架构与实践
« 上一篇 2022-06-17
  • vivo集装箱集群监控系统的架构与实践
    0阅读 0条评论 个赞
    vivo互联网服务器团队-YuanPeng一、概述从容器技术的推广以及Kubernetes成为容器调度管理领域的事实标准开始,云原生的理念和技术架构体系逐渐在生产环境中得到了越来越广泛的应用实践。……
  • 让事情变得更简单的8个高级Linux命令选项
    0阅读 0条评论 个赞
    随着Linux的发展,社区已经开发出标准Linux命令的强大替代方案。这里是其中的一些。当您学习Linux时,您可能会从Unix时代以来就存在的基本命令开始。但是,开发人员很久以前就创……
  • 什么样的数据有资格成为资产?
    0阅读 0条评论 个赞
    以下文章来源于公众号-大鱼的数据人生,作者讨厌的大鱼先生维克托·迈尔·舍恩伯格在《大数据时代》中曾经提到:“虽然数据还没有被列入企业的资产负债表,但这只是一个时间问题”。现在很多企业开始提数据是资产甚……
  • 3大问题!Redis缓存异常及处理方案综述
    0阅读 0条评论 个赞
    以下文章来源于公众号-云加社区,作者尹哲浩导语|Redis作为一个高性能的内存中的key-value数据结构存储系统,在我们日常开发中广泛应用于缓存、计数器、消息队列、排行榜等场景中,尤其是作为最常用……
  • 云原生后台运维改造的SRE实践
    0阅读 0条评论 个赞
    一、前言上一篇文章《云原生背景下的运维价值思考与实践(上)》重点介绍了云原生背景下运维转型的思考,围绕着整个DevOps交付链,贴近业务不断输出运维的能力与价值。这篇内容我想谈谈DevOps的……
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
  • 大数据平台核心架构图解 推荐收藏!
    1阅读 0条评论 个赞
    我们先来看看这张图,这是某公司使用的大数据平台架构图,大部分公司应该都差不多:从这张大数据的整体架构图上看来,大数据的核心层应该是:数据采集层、数据存储与分析层、数据共享层、数据应用层,可能叫法有所不……
  • 夯实基本功 深刻理解TLB原则
    0阅读 0条评论 个赞
    今天分享一篇TLB的好文章,希望大家夯实基本功,让我们一起深入理解计算机系统。TLB是translationlookasidebuffer的简称。首先,我们知道MMU的作用是把虚拟地址转换成物理地……
  • 如何在K8S的Pod中连续执行容器?不要错过这个方法
    1阅读 0条评论 个赞
    出于某些目的,有时需要在Kubernetes的一个Pod中,连续依次运行多个Container。这种有明确结束预期的运行,即Kubernetes的Job。但是,虽然一个Job可以在……
  • MySQL查询语句的准备阶段是什么?
    1阅读 0条评论 个赞
    以下文章来源于公众号--一树一溪,作者一树一溪这一篇主要讲的内容是一条简单查询语句,在查询准备阶段会干哪些事情?分3个部分:打开表select*替换为表字段填充where条件示例表及SQ……
  • 运维 放下监控——也放下自己
    1阅读 0条评论 个赞
    来源公众号:云原生技术应用(ID:sreguide)根据多年和运维打交道的经历,我发现,运维常常让监控变得无效。。。1.我的监控故事我做过两年多的运维工作,后面就转做运维平台开发了,也一步步看着监控……
  • 运维入坑必看:Kubernetes平台架构解读
    1阅读 0条评论 个赞
    Kubernetes是一个开源容器编排平台,管理大规模分布式容器化软件应用,是云计算发展演进的一次彻底革命性的突破。Kubernetes是谷歌的第三代容器管理系统,是Borg独特的控制器和Omega灵……
  • AI面试机器人后端架构实践
    0阅读 0条评论 个赞
    01导读AI面试机器人通过利用灵犀智能语音语义平台的人机语音对话能力模拟招聘者与求职者进行多轮语音沟通,达到在线化面试的效果。本文详细描述了AI面试机器人的后端架构组成、对话引擎设计、资源需求预估策略……
  • 写Python脚本 一定要加这个!
    1阅读 0条评论 个赞
    以下文章来源于公众号-Python技术,作者派森酱大家好,使用Python的人,平时经常会写一些脚本,不管是为了提升工作效率,还是为了满足一些特定的需求,Python脚本都是一个常见又有用的东西……
  • 用Docke r构建自己的dns服务器
    0阅读 0条评论 个赞
    在开发运维过程中经常需要自定义一个域名来管理服务,通常的方法是修改hosts文件,但还有一种更便捷的方法,从源头上解决问题,也就是使用DNS来实现。1.搭建搭建依然使用docker,安装前请安装好do……
  • 他山之石|查询理解在美团搜索中的应用
    0阅读 0条评论 个赞
    作者|刘亮美团资深算法工程在过去的20年中,搜索过程中处理查询的方式以及向用户显示结果的方式已完全改变。该过程已经从仅基于文本匹配的检索发展到现阶段——尝试基于对查询的真实语义理解以及上下文,位置,时……
  • 用MySQL写SQL的21个好习惯
    0阅读 0条评论 个赞
    前言每一个好习惯都是一笔财富,本文分SQL后悔药,SQL性能优化,SQL规范优雅三个方向,分享写SQL的21个好习惯,谢谢阅读,加油哈~1.写完SQL先explain查看执行计划(SQL性能优化)……
  • 数据库管理员必须学习的11个基本Linux命令
    0阅读 0条评论 个赞
    Linux系统庞大而复杂,经过总结,做为一名DBA,一些基本管理、网络管理、进阶应用、性能诊断、管道复杂应用、硬件相关传感命令都需要掌握,这篇文章,专门来讲做为一名DBA,必须学会的11个基本应用命令……
  • 运维!你要对数据心存敬畏~
    0阅读 0条评论 个赞
    简述“对数据要有敬畏之心”这个主题是同事在一个早会分享时提出的,却直接引起我心中的共鸣。前几年各种删库跑路事件、Facebook宕机事件仍不绝于耳,虽然大家将“删库跑路”当作一个调侃与谈资,但上升到“……
  • 在学校教授Python编程的理想IDE
    0阅读 0条评论 个赞
    在Linux中运行Python程序就像在终端中执行Python文件一样简单。但这对大多数人来说都不是很方便,也无助于调试程序。有多种IDE和文本编辑器可用于Python开发。PyC……
  • 无监控 无运维!普罗米修斯在线服务监控实用指南
    1阅读 0条评论 个赞
    本文可以看做是对《SRE》一书第10章《基于时间序列数据进行有效报警》的实践总结。Prometheus是一款开源的业务监控软件,可以看作是Google内部监控系统Borgmon的一个(非官方)实现……
  • Linux程序编译过程的来龙去脉
    1阅读 0条评论 个赞
    大家肯定都知道计算机程序设计语言通常分为机器语言、汇编语言和高级语言三类。高级语言需要通过翻译成机器语言才能执行,而翻译的方式分为两种,一种是编译型,另一种是解释型,因此我们基本上将高级语言分为两大类……
  • 还记得发现redis使用不当导致的应用卡顿bug的过程吗?
    1阅读 0条评论 个赞
    首先说下问题现象:内网sandbox环境API持续1周出现应用卡死,所有api无响应现象。刚开始当测试抱怨环境响应慢的时候,我们重启一下应用,应用恢复正常,于是没做处理。但是后来问题出现频率越来越频……
  • SQL中左连接左表合并去重实用技巧
    3阅读 0条评论 个赞
    zyc88.blog.csdn.net/article/details/83002882建表:CREATETABLE`table1`(`id`int(11)NOTNULLAUTO_INCREMENT,……
  • 重温SQL Server的行到列和列到列的变化 并采访常见问题
    1阅读 0条评论 个赞
    行转列,列转行是我们在开发过程中经常碰到的问题。行转列一般通过CASEWHEN语句来实现,也可以通过SQLSERVER的运算符PIVOT来实现。用传统的方法,比较好理解。层次清晰,而且比较习……
  • 码头工人常见问题处理技巧
    1阅读 0条评论 个赞
    本文列举Docker常见问题24个及解决方法:▍1.Docker迁移存储目录默认情况系统会将Docker容器存放在/var/lib/docker目录下[问题起因]今天通过监控系统,发现公……
最近发布资讯
更多