SpringBoot引入Nginx负载均衡实现Session共享

Nginx简介

Nginx 是一个高性能的 HTTP 和反向代理 web 服务器,同时也提供了 IMAP/POP3/SMTP 服务。
Nginx 特点是占有内存少,并发能力强。
事实上 nginx 的并发能力确实在同类型的网页服务器中表现较好,一般来说,如果我们在项目中引入了 Nginx ,我们的项目架构可能是这样:
在这里插入图片描述
在这样的架构中 , Nginx 所代表的角色叫做负载均衡服务器或者反向代理服务器,所有请求首先到达 Nginx 上,再由 Nginx 根据提前配置好的转发规则,将客户端发来的请求转发到某一个 Tomcat 上去。

那么这里涉及到两个概念:

  • 负载均衡服务器

就是进行请求转发,降低某一个服务器的压力。负载均衡策略很多,也有很多层,对于一些大型网站基本上从 DNS 就开始负载均衡,负载均衡有硬件和软件之分,各自代表分别是 F5 和 Nginx (目前 Nginx 已经被 F5 收购),早些年,也可以使用 Apache 来做负载均衡,但是效率不如 Nginx ,所以现在主流方案是 Nginx 。

  • 反向代理服务器

另一个概念是反向代理服务器,得先说正向代理,看下面一张图:
在这里插入图片描述
在这个过程中,Google 并不知道真正访问它的客户端是谁,它只知道这个中间服务器在访问它。因此,这里的代理,实际上是中间服务器代理了客户端,这种代理叫做正向代理。

那么什么是反向代理呢?看下面一张图:
在这里插入图片描述
在这个过程中,10086 这个号码相当于是一个代理,真正提供服务的,是话务员,但是对于客户来说,他不关心到底是哪一个话务员提供的服务,他只需要记得 10086 这个号码就行了。

所有的请求打到 10086 上,再由 10086 将请求转发给某一个话务员去处理。因此,在这里,10086 就相当于是一个代理,只不过它代理的是话务员而不是客户端,这种代理称之为反向代理。

Session共享

前几天在上班的时候碰到用户提出来的一个小问题:用户登录后进行常规操作,不一会就会弹出到登陆页面。其实这就是一个由多个服务会引发的问题:Session共享;为什么呢?简单的描述一下:在传统的单服务架构中,一般来说,只有一个服务器,那么不存在 Session 共享问题,但是在分布式/集群项目中,Session 共享则是一个必须面对的问题,先看一个简单的架构图:
在这里插入图片描述
客户端发起一个请求,这个请求到达 Nginx 上之后,被 Nginx 转发到 Tomcat A 上,然后在 Tomcat A 上往 session 中保存了一份数据,下次又来一个请求,这个请求被转发到 Tomcat B 上,此时再去 Session 中获取数据,发现没有之前的数据。对于这一类问题的解决,思路很简单,就是将各个服务之间需要共享的数据,保存到一个公共的地方(主流方案就是 Redis):
在这里插入图片描述
当所有 Tomcat 需要往 Session 中写数据时,都往 Redis 中写,当所有 Tomcat 需要读数据时,都从 Redis 中读。这样,不同的服务就可以使用相同的 Session 数据了。

实战

首先创建项目时,我们需要如下依赖:
在这里插入图片描述
随后配置application.propertis,只需一些Redis的配置即可:

spring.redis.host=0.0.0.0
spring.redis.password=123
spring.redis.port=6379
spring.redis.database=1

创建一个Controller用来测试:

@RestController
public class Hello {

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

    @GetMapping("/set")
    public String set(HttpSession session) {
        session.setAttribute("name", "javaBoy");
        return String.valueOf(port);
    }

    @GetMapping("/get")
    public String get(HttpSession session) {
        return (String) session.getAttribute("name") + port;
    }
}

其中port在我们运行jar的时候指定不同的端口,从而更直观的查看我们想看到的。当我们在访问set接口的时候,像Session中存住了一个数据,并打印出当前的端口A。/get端口获取到A端口的数据+B端口;然后使用maven将项目打包:
在这里插入图片描述
此处需要注意,打包前先将test屏蔽掉,不然打包的时候会报错;完成后在项目的目录中target目录中,就可看到我们生成的jar包。这个地方需要注意,如果打包后但是在idea中未显示target文件夹,我们需要这样设置一下:
在这里插入图片描述
将Show Excluded Files选中,在Terminal中运行实例:

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

项目启动后,我们在浏览器中便可访问不同端口下的set./get方法。这里便不一一描述。。。

引入Nginx

很简单,进入 Nginx 的安装目录的 conf 目录下(默认是在 /usr/local/nginx/conf),编辑 nginx.conf 文件:
在这里插入图片描述
在这段配置中:

  1. javaboy表示服务器集群的名字,这个可以随意取名字
  2. upstream 里边配置的是一个个的单独服务
  3. weight 表示服务的权重,意味者将有多少比例的请求从 Nginx 上转发到该服务上
  4. location 中的 proxy_pass 表示请求转发的地址,/ 表示拦截到所有的请求,转发转发到刚刚配置好的服务集群中
  5. upstream 表示配置上游服务器
  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 > 8080.log &
nohup java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8081 > 8080.log &

其中

  • nohup 表示当终端关闭时,Spring Boot 不要停止运行
  • & 表示让 Spring Boot 在后台启动
  • 8080.log 表示记录日志

配置完成后,重启 Nginx:

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

Nginx 启动成功后,我们首先手动清除 Redis 上的数据,然后访问 0.0.0.0/set 表示向 session 中保存数据,这个请求首先会到达 Nginx 上,再由 Nginx 转发给某一个 Spring Boot 实例:
在这里插入图片描述
如上,表示端口为 8081 的 Spring Boot 处理了这个 /set 请求,再访问 /get 请求:
在这里插入图片描述
可以看到,/get 请求是被端口为 8080 的服务所处理的。
这里当我们访问的接口的时候,需要登录。之前密码是在控制台中我们直接复制就OK的,这次也是一样,项目启动日志记录在我们之前设置好的8080.log中:
在这里插入图片描述

总结

到现在我们的SpringBoot引入Nginx负载均衡实现Session共享已经完成啦!其实很简单!只需要引入依赖即可!我们写了一些代码,也做了一些配置,但是全都和 Spring Session 无关,配置是配置 Redis,代码就是普通的 HttpSession,和 Spring Session 没有任何关系!唯一和 Spring Session 相关的,可能就是我在一开始引入了 Spring Session 的依赖吧!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值