有的人可能会觉得题目有点夸张,其实不夸张,题目没有使用任何修辞手法!认真读完本文,你就知道松哥说的是对的了!

在传统的单服务架构中,一般来说,只有一个服务器,那么不存在 Session 共享问题,但是在分布式/集群项目中,Session 共享则是一个必须面对的问题,先看一个简单的架构图:

在这样的架构中,会出现一些单服务中不存在的问题,例如客户端发起一个请求,这个请求到达 Nginx 上之后,被 Nginx 转发到 Tomcat A 上,然后在 Tomcat A 上往 session 中保存了一份数据,下次又来一个请求,这个请求被转发到 Tomcat B 上,此时再去 Session 中获取数据,发现没有之前的数据。对于这一类问题的解决,思路很简单,就是将各个服务之间需要共享的数据,保存到一个公共的地方(主流方案就是 Redis):

当所有 Tomcat 需要往 Session 中写数据时,都往 Redis 中写,当所有 Tomcat 需要读数据时,都从 Redis 中读。这样,不同的服务就可以使用相同的 Session 数据了。

这样的方案,可以由开发者手动实现,即手动往 Redis 中存储数据,手动从 Redis 中读取数据,相当于使用一些 Redis 客户端工具来实现这样的功能,毫无疑问,手动实现工作量还是蛮大的。

一个简化的方案就是使用 Spring Session 来实现这一功能,Spring Session 就是使用 Spring 中的代理过滤器,将所有的 Session 操作拦截下来,自动的将数据 同步到 Redis 中,或者自动的从 Redis 中读取数据。

对于开发者来说,所有关于 Session 同步的操作都是透明的,开发者使用 Spring Session,一旦配置完成后,具体的用法就像使用一个普通的 Session 一样。

1 实战

1.1 创建工程

首先 创建一个 Spring Boot 工程,引入 Web、Spring Session 以及 Redis:

创建成功之后,pom.xml 文件如下:

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

注意:

这里我使用的 Spring Boot 版本是 2.1.4 ,如果使用当前最新版 Spring Boot2.1.5 的话,除了上面这些依赖之外,需要额外添加 Spring Security 依赖(其他操作不受影响,仅仅只是多了一个依赖,当然也多了 Spring Security 的一些默认认证流程)。

1.2 配置 Redis

spring.redis.host=192.168.66.128
spring.redis.port=6379
spring.redis.password=123
spring.redis.database=0

这里的 Redis ,我虽然配置了四行,但是考虑到端口默认就是 6379 ,database 默认就是 0,所以真正要配置的,其实就是两行。

1.3 使用

配置完成后 ,就可以使用 Spring Session 了,其实就是使用普通的 HttpSession ,其他的 Session 同步到 Redis 等操作,框架已经自动帮你完成了:

@RestController
public class HelloController {
@Value("${server.port}")
Integer port;
@GetMapping("/set")
public String set(HttpSession session) {
session.setAttribute("user", "javaboy");
return String.valueOf(port);
}
@GetMapping("/get")
public String get(HttpSession session) {
return session.getAttribute("user") + ":" + port;
}
}

考虑到一会 Spring Boot 将以集群的方式启动 ,为了获取每一个请求到底是哪一个 Spring Boot 提供的服务,需要在每次请求时返回当前服务的端口号,因此这里我注入了 server.port 。

接下来 ,项目打包:

打包之后,启动项目的两个实例:

java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8080
java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8081

然后先访问 localhost:8080/set8080 这个服务的 Session 中保存一个变量,访问完成后,数据就已经自动同步到 Redis 中 了 :

然后,再调用 localhost:8081/get 接口,就可以获取到 8080 服务的 session 中的数据:

此时关于 session 共享的配置就已经全部完成了,session 共享的效果我们已经看到了,但是每次访问都是我自己手动切换服务实例,因此,接下来我们来引入 Nginx ,实现服务实例自动切换。

1.4 引入 Nginx

很简单,进入 Nginx 的安装目录的 conf 目录下(默认是在 /usr/local/nginx/conf),编辑 nginx.conf 文件:

在这段配置中:

  1. upstream 表示配置上游服务器
  2. javaboy.org 表示服务器集群的名字,这个可以随意取名字
  3. upstream 里边配置的是一个个的单独服务
  4. weight 表示服务的权重,意味者将有多少比例的请求从 Nginx 上转发到该服务上
  5. location 中的 proxy_pass 表示请求转发的地址,/ 表示拦截到所有的请求,转发转发到刚刚配置好的服务集群中
  6. proxy_redirect 表示设置当发生重定向请求时,nginx 自动修正响应头数据(默认是 Tomcat 返回重定向,此时重定向的地址是 Tomcat 的地址,我们需要将之修改使之成为 Nginx 的地址)。

配置完成后,将本地的 Spring Boot 打包好的 jar 上传到 Linux ,然后在 Linux 上分别启动两个 Spring Boot 实例:

nohup java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8080 &
nohup java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8081 &

其中

  • nohup 表示当终端关闭时,Spring Boot 不要停止运行
  • & 表示让 Spring Boot 在后台启动

配置完成后,重启 Nginx:

/usr/local/nginx/sbin/nginx -s reload

Nginx 启动成功后,我们首先手动清除 Redis 上的数据,然后访问 192.168.66.128/set 表示向 session 中保存数据,这个请求首先会到达 Nginx 上,再由 Nginx 转发给某一个 Spring Boot 实例:

如上,表示端口为 8081Spring Boot 处理了这个 /set 请求,再访问 /get 请求:

可以看到,/get 请求是被端口为 8080 的服务所处理的。

2 总结

本文主要向大家介绍了 Spring Session 的使用,另外也涉及到一些 Nginx 的使用 ,虽然本文较长,但是实际上 Spring Session 的配置没啥。

我们写了一些代码,也做了一些配置,但是全都和 Spring Session 无关,配置是配置 Redis,代码就是普通的 HttpSession,和 Spring Session 没有任何关系!

唯一和 Spring Session 相关的,可能就是我在一开始引入了 Spring Session 的依赖吧!

如果大家没有在 SSM 架构中用过 Spring Session ,可能不太好理解我们在 Spring Boot 中使用 Spring Session 有多么方便,因为在 SSM 架构中,Spring Session 的使用要配置三个地方 ,一个是 web.xml 配置代理过滤器,然后在 Spring 容器中配置 Redis,最后再配置 Spring Session,步骤还是有些繁琐的,而 Spring Boot 中直接帮我们省去了这些繁琐的步骤!不用再去配置 Spring Session。

好了 ,本文就说到这里,本文相关案例我已经上传到 GitHub ,大家可以自行下载:https://github.com/lenve/javaboy-code-samples

关注公众号【江南一点雨】,专注于 Spring Boot+微服务,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!

Spring Boot 一个依赖搞定 session 共享,没有比这更简单的方案了!的更多相关文章

  1. SpringBoot一个依赖搞定session共享

    原文:微信公众号:Java开发宝典  https://mp.weixin.qq.com/s/_VFY9lXqNhH8Nh4HC9tuMg 1. 前言 在传统的单服务架构中,一般来说,只有一个服务器,那 ...

  2. 将你的前端应用打包成docker镜像并部署到服务器?仅需一个脚本搞定

    1.前言 前段时间,自己搞了个阿里云的服务器.想自己在上面折腾,但是不想因为自己瞎折腾而污染了现有的环境.毕竟,现在的阿里云已经没有免费的快照服务了.要想还原的话,最简单的办法就是重新装系统.而一旦重 ...

  3. Spring Boot起步依赖:定制starter

    在定制我们自己的起步依赖--xxx.spring.boot.starter之前,我们先了解下什么是Spring Boot起步依赖. 起步依赖,是Spring Boot带给我们的一项重要的便利.要理解S ...

  4. python技巧一行命令搞定局域网共享

    python超强玩法--一行命令搞定局域网共享 ​ 今天刷到python的一个新玩法,利用python自带的http服务,快速创建局域网共享服务,命令如下: python -m thhp.server ...

  5. Jquery一个slideToggle搞定div的隐藏与显示

    Jquery一个slideToggle搞定div的隐藏与显示 <!DOCTYPE html> <html> <head> <script src=" ...

  6. SpringBoot 之Spring Boot Starter依赖包及作用

    Spring Boot 之Spring Boot Starter依赖包及作用 spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置.日志和YAML. spri ...

  7. 一个命令搞定 Web 国际化

    背景 随着出海的业务越来越多,web 应用面临越来越多的国际化的工作.如何高效,高质量的完成 Web 前端国际化工作,已经是摆在 web 前端同学的急需解决的问题. i18n-helper-cli 是 ...

  8. 【项目实践】一文带你搞定Session和JWT的登录认证方式

    以项目驱动学习,以实践检验真知 前言 登录认证,估计是所有系统中最常见的功能了,并且也是最基础.最重要的功能.为了做好这一块而诞生了许多安全框架,比如最常见的Shiro.Spring Security ...

  9. 【源码解析】凭什么?spring boot 一个 jar 就能开发 web 项目

    问题 为什么开发web项目,spring-boot-starter-web 一个jar就搞定了?这个jar做了什么? 通过 spring-boot 工程可以看到所有开箱即用的的引导模块 spring- ...

随机推荐

  1. 腾讯WeTest兼容服务再次升级,支持小程序兼容

    WeTest 导读 小程序作为微信内能被便捷地获取和传播的工具,吸引着越来越多的开发者加入其中.无论是小游戏.零售.出行服务还是生活餐饮等,各行各业的小程序出现在用户的手机上,在给用户带来便利的同时, ...

  2. 技能篇丨FineCMS 5.0.10 多个漏洞详细分析

    今天是一篇关于技能提升的文章,文章中的CMS是FineCMS,版本是5.0.10版本的几个漏洞分析,主要内容是介绍漏洞修补前和修补后的分析过程,帮助大家快速掌握该技能. 注:篇幅较长,阅读用时约7分钟 ...

  3. ios开发的技巧

    http://www.cocoachina.com/ios/20141231/10783.html

  4. vue-cli3.0创建项目之完成登录页面

    借鉴博客:https://www.cnblogs.com/KenFine/p/10850386.html 接着上一个创建的新项目vue-mydemo01来: 1.创建一个login.vue组件页面:如 ...

  5. jQuery中的index用法与inArray用法

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  6. vue定时器+弹框 跳到登陆页面

    1.做一个请求拦截,并弹框提示几秒后,跳转到登陆首页或是点击确定之后直接跳转拦截用了this.$axios.interceptors.response页面上的弹框组件用了vux的组件vux地址:htt ...

  7. 查看 JVM 默认参数

    -XX:+PrintFlagsFinal 可以获取所有可设置参数及值 获取 JVM 默认 Xss 大小 java -XX:+PrintFlagsFinal -version | grep Thread ...

  8. 服务器Oracle数据库配置与客户端访问数据库的一系列必要设置

    tips:所有路径请对应好自己电脑的具体文件路径. 一.服务器及Oracle数据库设置 1.刚装完的Oracle数据库中只有一个dba账户,首先需要创建一个用户. 2.配置监听,C:\app\Admi ...

  9. Django框架(二十)-- Django rest_framework-权限组件

    一.权限组件的使用 # 用户信息表 class UserInfo(models.Model): name = models.CharField(max_length=32) # 写choice use ...

  10. Shel脚本-初步入门之《03》

    Shel脚本-初步入门-Shell 脚本在 Linux 运维工作中的地位 3.Shell 脚本在 Linux 运维工作中的地位 Shell 脚本语言很适合用于处理纯文本类型的数据,而 Linux 系统 ...