网易首页 > 网易号 > 正文 申请入驻

面试难题:分布式 Session 实现难点,这篇就够!

0
分享至


  • 那如何来解决分布式Session问题呢?

    • 一、解决方案列举

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

平常做的项目都是在一台应用系统,并且所有的操作都在一台Tomcat服务器上,并不会引发Session共享的问题,所以并不会对我们的系统产生影响,但是当我们部署多个微服务的时候,再搭配Nginx进行负载均衡时,如果不处理分布式Session问题,我们在系统中访问不同功能时就会频繁出现用户登录的操作

图解分析原因:

图片

前提:用户登录功能和图中的商品订单模块、秒杀抢购模块属于单独的微服务模块用户登录成功后想要访问图中其他两个模块的功能时,由于Nginx使用默认负载均衡策略(轮询),这时请求会按照时间顺序逐一分发到后端应用上,也就是说用户在Tomcat1上登录成功之后,用户的信息放在Tomcat1Session里,过了一会,用户想要进行秒杀活动的功能操作,请求又被Nginx分发到了Tomcat2,而这时的Tomcat2上的Session里还没有用户信息,于是就是出现让用户重新登录的情况,在微服务分布式项目中,不同的功能模块必然会被分列成各自的微服务,假设访问一个功能都需要重新登录一次,用户的体验必然会大幅度下降!

那如何来解决分布式Session问题呢?一、解决方案列举 1. Session复制

优点:

  • 无需修改代码,只需要修改Tomcat配置

缺点:

  • 同步传输占用内网宽带

  • 多台Tomcat同步性能指数级下降

  • Session占用内存,无法有效水平扩展

2. 前端存储

优点:

  • 不占用服务器内存

缺点:

  • 存在安全风险

  • 数据大小受cookie限制

  • 占用外网宽带

3. Session粘滞

优点:

  • 无需修改代码

  • 服务端可以水平扩展

缺点:

  • 增加新机器,会重新Hash,导致重新登录

  • 应用重新启动后,需要重新登录

4. 后端集中存储

优点:

  • 安全

  • 容易水平扩展

优点:

  • 增加复杂度

  • 需要修改代码

  • 另外, 面试宝典:https://www.yoodb.com即将上线

二、Java代码实现解决分布式Session 1. SpringSession - Redis解决分布式Session
添加依赖

org.springframework.boot
spring-boot-starter-data-redis

org.apache.commons
commons-pool2

org.springframework.session
spring-session-data-redis

添加Redis配置
## Redis配置
spring:
redis:
服务器地址
host: localhost
端口
port: 6379
数据库
database: 0
超时时间
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";
}

登录测试

图片

2. Redis解决分布式Session

导入依赖

org.springframework.boot
spring-boot-starter-data-redis

org.apache.commons
commons-pool2

业务逻辑层
@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管理工具

图片

作者:派 大 星. https://blog.csdn.net/Gaowumao/article/details/124309548

公众号“Java精选”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理!

最近有很多人问,有没有读者交流群!加入方式很简单,公众号Java精选,回复“加群”,即可入群!

(微信小程序):3000+道面试题,包含Java基础、并发、JVM、线程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架构设计等,在线随时刷题!

------ 特别推荐 ------

特别推荐:专注分享最前沿的技术与资讯,为弯道超车做好准备及各种开源项目与高效率软件的公众号,「大咖笔记」,专注挖掘好东西,非常值得大家关注。点击下方公众号卡片关注

文章有帮助的话,点在看,转发吧!

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
秦岚魏大勋疑分手,传男方向女方求婚遭拒,杨幂无辜躺枪

秦岚魏大勋疑分手,传男方向女方求婚遭拒,杨幂无辜躺枪

不八卦会死星人
2024-06-12 17:18:40
阿联酋部长称美国对中东成为中国AI代理的担忧是合理的

阿联酋部长称美国对中东成为中国AI代理的担忧是合理的

cnBeta.COM
2024-06-12 18:38:06
燃油耗尽的客机飞向日本迫降遭日方拒绝,机长将一名男子踹出飞机

燃油耗尽的客机飞向日本迫降遭日方拒绝,机长将一名男子踹出飞机

梦里大唐
2024-06-12 17:51:34
印度破纪录了!首都将不再适合人类居住?恒河都被洗到“勾芡”

印度破纪录了!首都将不再适合人类居住?恒河都被洗到“勾芡”

回京历史梦
2024-06-12 18:25:38
请求中方取消禁令被拒绝,日本开始来硬的,岸田敲定制裁中企名单

请求中方取消禁令被拒绝,日本开始来硬的,岸田敲定制裁中企名单

王大健美食日常
2024-06-13 14:48:04
女生胸太大运动起来有多辛苦?妹子纷纷晒图…真的被她们装到了

女生胸太大运动起来有多辛苦?妹子纷纷晒图…真的被她们装到了

经典段子
2024-06-11 23:37:28
刘亦菲的身高到底是多少

刘亦菲的身高到底是多少

李保军财经
2024-06-11 22:35:58
笑不活了,现在小孩子的身高就是个谜,要被评论区笑死了

笑不活了,现在小孩子的身高就是个谜,要被评论区笑死了

奇特短尾矮袋鼠
2024-06-11 18:42:16
拒绝萨林杰+陈国豪!广东队今夏扶正第一人!他才是宏远锋线答案

拒绝萨林杰+陈国豪!广东队今夏扶正第一人!他才是宏远锋线答案

绯雨儿
2024-06-13 14:06:16
浙江海宁试点商品房“以旧换新”:存量住房评估总价不得高于新房总价60%

浙江海宁试点商品房“以旧换新”:存量住房评估总价不得高于新房总价60%

澎湃新闻
2024-06-13 14:36:28
女孩高考完收到3年前订的花,得知送花的人当场泪崩:他没有骗我

女孩高考完收到3年前订的花,得知送花的人当场泪崩:他没有骗我

老王侃趣闻
2024-06-13 15:45:07
为了钱我做了一名奶妈,喂养完老板的儿子,还要加班照顾老板

为了钱我做了一名奶妈,喂养完老板的儿子,还要加班照顾老板

亲爱的落落
2023-05-24 21:42:14
降维打击!31岁前国手赴美打野球 秀穿档晃飞防守人 称霸路人局

降维打击!31岁前国手赴美打野球 秀穿档晃飞防守人 称霸路人局

林小湜体育频道
2024-06-12 23:21:57
头部主播卖不动货,抖音急了

头部主播卖不动货,抖音急了

市界
2024-06-13 14:12:26
有无可能❓六台记者:如果葡萄牙欧洲杯夺冠,C罗就将赢得金球奖

有无可能❓六台记者:如果葡萄牙欧洲杯夺冠,C罗就将赢得金球奖

直播吧
2024-06-12 21:21:08
最新数据!燃油车销量暴跌

最新数据!燃油车销量暴跌

中国基金报
2024-06-11 22:08:59
70岁成龙被指断崖式衰老,近况曝光秒回春似壮年

70岁成龙被指断崖式衰老,近况曝光秒回春似壮年

葫芦哥爱吐槽
2024-06-13 02:39:28
不愧是一生要强的中国女人,月薪高达13万,网友:这确实是该得的

不愧是一生要强的中国女人,月薪高达13万,网友:这确实是该得的

四象八卦
2024-06-12 21:17:26
游客在四川一景区被瀑布落石砸中,当地:不幸身亡,正积极善后

游客在四川一景区被瀑布落石砸中,当地:不幸身亡,正积极善后

潇湘晨报
2024-06-13 13:32:06
还剩7600亿美债,中国对美开出第三张罚单,沙利文一语激起千层浪

还剩7600亿美债,中国对美开出第三张罚单,沙利文一语激起千层浪

战未央
2024-06-12 10:28:39
2024-06-13 16:32:49
Java精选
Java精选
一场永远也演不完的戏
1551文章数 3855关注度
往期回顾 全部

科技要闻

"在小红书,员工是实验品,不好用就扔掉"

头条要闻

山东沂蒙山区持续干旱:桃农排队浇地 玉米种了不出苗

头条要闻

山东沂蒙山区持续干旱:桃农排队浇地 玉米种了不出苗

体育要闻

杰里·韦斯特:为什么他是LOGO?

娱乐要闻

森林北报案,称和汪峰的感情遭受压力

财经要闻

徽商银行的影子 借基金向地方城投放贷?

汽车要闻

升级8155芯片 新款卡罗拉锐放将于今日上市

态度原创

游戏
健康
手机
教育
本地

预售仅四天 《黑神话:悟空》登顶Steam周销榜

晚餐不吃or吃七分饱,哪种更减肥?

手机要闻

OPPO Reno 12系列将于下周全球发布 但芯片被大砍一刀

教育要闻

中专女生爆冷拿下数学竞赛全球12名

本地新闻

粽情一夏|海河龙舟赛,竟然成了外国人的大party!

无障碍浏览 进入关怀版