SpringBoot - 结合Redis实现Session共享、结合Nginx实现负载均衡(请求分发)
作者:hangge | 2019-12-25 08:10
如果我们需要对项目进行横向扩展搭建集群,那么可以利用一些硬件或者软件工具(比如 Nginx)来做负载均衡,此时,来自同一个用户的 HTTP 请求就有可能被分发到不同的实例上去,如何保证各个实例之间 Session 的同步就成为一个必须解决的问题。
当一个请求到达 Nginx 服务器上时,首先请求分发,假设请求被 server1 处理了,server1 在处理请求时,无论存储还是读取 session 的操作,都是去操作 session 服务器而不是自身内存中的 session,其他 server 也是如此,这样就实现了 session 共享。
(2)接着在 application.properties 中配置 Redis 连接信息:
(2)如果上面执行后可能会显示“nohup: 忽略输入并把输出追加到"nohup.out"”,我们直接回车即可。
(2)然后进入解压目录中执行编译安装:
(3)安装成功后,找到 Nginx 安装目录,执行 sbin 目录下的 nginx 文件启动 nginx,命令如下:
(4)启动后默认端口是 80,我们可以使用浏览器直接访问:
(2)对 nginx.conf 文件进行编辑,编辑内容如下:
(3)配置完成后,执行如下命令重启 Nginx:
Spring Boot 提供了自动化的 Session 共享配置,它结合 Redis 可很方便地解决这个问题。使用 Redis 解决 session 共享的原理非常简单,就是把原本储存在不同服务器上的 session 拿出来放到一个独立的服务器上:
一、结合 Redis 进行 Session 共享配置
1,Redis 安装
首先我们需要一个 Redis 服务来作为 Session 服务器,Redis 的安装可以参考我之前的文章:
2,项目配置
(1)编辑 pom.xml 文件,添加 Redis 和 Session 依赖: 除了 Redis 依赖之外,这里还要提供 spring-session-data-redis 依赖,Spring Session 可以做到透明化地替换掉应用的 Session 容器。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>
(2)接着在 application.properties 中配置 Redis 连接信息:
# 基本连接信息配置
spring.redis.database=0
spring.redis.host=192.168.60.133
spring.redis.port=6379
spring.redis.password=123
# 连接池信息配置
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.max-wait=-1ms
spring.redis.jedis.pool.min-idle=0
3,创建测试接口
创建一个 Contoller 用来执行测试操作,里面提供了两个方法:一个 save 接口用来向 Session 中存储数据,还有一个 get 接口用来从 Session 中获取数据。- 为方便演示,这里注入了项目启动的端口号 server.port,主要是为了区分到底是哪个服务器提供的服务。
- 虽然这里还是操作的 HttpSession,但是实际上 HttpSession 容器已经被透明替换,真正的 Session 此时存储在 Redis 服务器上。
@RestController public class HelloController { @Value("${server.port}") String port; @GetMapping("/save/{name}") public String saveName(@PathVariable("name")String name, HttpSession session) { session.setAttribute("name", name); return port; } @GetMapping("/get") public String getName(HttpSession session) { Object s =session.getAttribute("name"); return port + ":" + session.getAttribute("name").toString(); } }
4,运行项目
(1)最后将项目打成 jar 包上传到 CentOS 上,然后执行如下两条命令启动 2 个项目(使用不同端口):
nohup 表示不挂断程序运行,即当终端窗口关闭后,程序依然在后台运行,最后的 & 表示让程序在后台运行。
nohup java -jar demo-0.0.1-SNAPSHOT.jar --server.port=8080 & nohup java -jar demo-0.0.1-SNAPSHOT.jar --server.port=8081 &
(2)如果上面执行后可能会显示“nohup: 忽略输入并把输出追加到"nohup.out"”,我们直接回车即可。
5,开始测试
(1)首先我们访问 8080 这个项目的 /save 接口存放一个 session:
(2)接着访问 8081 项目的 /get 接口获取 session,可以发现虽然它们是不同的项目,但是 session 是共享的。
二、使用 Nginx 实现负载均衡
1,安装运行
(1)首先下载 Nginx 源码并解压:wget https://nginx.org/download/nginx-1.17.0.tar.gz tar -zxvf nginx-1.17.0.tar.gz
(2)然后进入解压目录中执行编译安装:
cd nginx-1.17.0 ./configure make make install
(3)安装成功后,找到 Nginx 安装目录,执行 sbin 目录下的 nginx 文件启动 nginx,命令如下:
/usr/local/nginx/sbin/nginx
(4)启动后默认端口是 80,我们可以使用浏览器直接访问:
2,修改配置文件
(1)接下来进入 Nginx 安装目录修改配置文件:
vi /usr/local/nginx/conf/nginx.conf
(2)对 nginx.conf 文件进行编辑,编辑内容如下:
修改说明:
- 首先配置上游服务器,即两个 real server,两个 real server 的权重都是 1,意味着请求将平均分配到两个 real server 上。
- 然后在 server 中配置拦截规则,将拦截到的请求转发到定义好的 real server 上。
upstream hangge.com { server 192.168.60.133:8080 weight=1; server 192.168.60.133:8081 weight=1; } server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { proxy_pass http://hangge.com; proxy_redirect default; }
(3)配置完成后,执行如下命令重启 Nginx:
/usr/local/nginx/sbin/nginx -s reload
3,请求分发测试
(1)首先调用 /save 接口存储数据。下图可以看到虽然调用的端口是 80,但实际请求被 Nginx 服务器转发到 8081 这个服务上:(2)接着调用 /get 接口获取数据,可以看到这次请求被分发到 8080 这个服务上。同时也可以发现,它们的 session 是共享的。
全部评论(0)