返回 导航

SpringBoot / Cloud

hangge.com

SpringBoot - 结合Redis实现Session共享、结合Nginx实现负载均衡(请求分发)

作者:hangge | 2019-12-25 08:10
    如果我们需要对项目进行横向扩展搭建集群,那么可以利用一些硬件或者软件工具(比如 Nginx)来做负载均衡,此时,来自同一个用户的 HTTP 请求就有可能被分发到不同的实例上去,如何保证各个实例之间 Session 的同步就成为一个必须解决的问题。
    Spring Boot 提供了自动化的 Session 共享配置,它结合 Redis 可很方便地解决这个问题。使用 Redis 解决 session 共享的原理非常简单,就是把原本储存在不同服务器上的 session 拿出来放到一个独立的服务器上:

    当一个请求到达 Nginx 服务器上时,首先请求分发,假设请求被 server1 处理了,server1 在处理请求时,无论存储还是读取 session 的操作,都是去操作 session 服务器而不是自身内存中的 session,其他 server 也是如此,这样就实现了 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)

回到顶部