Spring Boot2.x+Redis实现SpringSession一致性

Nginx+Redis+Spring Boot实现session一致性

Spring Boot应用通常会部署在多个Web服务器上同时提供服务,我们称之为水平拓展。
Spring Boot 应用水平扩展有两个问题需要解决,一个是将用户的请求派发到水平部署的任意一台Spring Boot应用,通常用一个反向代理服务器来实现,如使用Nginx作为反向代理。
另外一个需要解决的问题是会话管理, 单个Spring Boot 应用的会话由Tomcat 来管理,会话信息与Tomcat 存放在一起。如果部署多个Spring Boot 应用,对于同一个用户请求,即使请求通过Nginx 派发到不同的Web 服务器上,也能共享会话信息。
集中式会话: 所有Web 服务器都共享一个会话,会话信息通常存放在一台服务器上,本文使用Redis服务器来存放会话。

  • 1、安装Nginx
  • 2、配置Nginx
  • 3、Spring Session介绍
  • 4、使用Redis
  • 5、验证

1、安装Nginx

Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3 )、TCP/UDP代理服务器,并在一个BSD-like 协议下发行。 —— [ Nginx官网 ]

打开Nginx网站,点击download进入下载页面,根据自己的操作系统选择下载,以windows系统为例,下载nginx/Windows-1.14.0版本,直接解压,然后运行Nginx即可。
Nginx默认监听80端口 启动后,可以访问http://127.0.0.1:80 ,会看到Nginx 的欢迎页面。如下图所示。
Spring Boot2.x+Redis实现SpringSession一致性_第1张图片

2、配置Nginx

Nginx 的配置文件conf/nginx.conf 下包含多个指令块,我们主要关注http块和location 块。
http块:可以嵌套多个Server ,配置代理、缓存、日志定义等绝大多数功能和第三方模块,如mime-type 定义、日志自定义、是否使用sendfile 传输文件、连接超时时间、单连接请求数等。
location 块:配置请求的路由,以及各种页面的处理情况。

我们需要在http 块中增加upstream 指令,内容如下:

http {
    upstream backend {
        server 127.0.0.1:9000;
        server 127.0.0.1:9001;
    }
}

backend 也可以为任意名字,我们在下面的配置将要引用到:

 location / {
            proxy_pass http://backend;
        }

location后可以是一个正则表达式,我们这里用“ / ”表示所有客户端请求都会传给http://backend,也就是我们配置的backend指令的地址列表。因此,整个http块类似下面的样子:

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    upstream backend {
        server 127.0.0.1:9000;
        server 127.0.0.1:9001;
    }

    server {
        listen       80;
        server_name  localhost;

        location / {
            proxy_pass http://backend;
        }

    }

我们在后面将创建一个Spring Boot 应用,并分别以9000 和9001两个端口启动,然后在Spring Session 的基础上一步步来完成Spring Boot 应用的水平扩展。

3、Spring Session介绍

在默认情况下, Spring Boot 使用Tomcat 服务器的Session 实现,我们编写一个例子用于测试:

@Slf4j
@Controller
public class SpringSessionCrontroller {

    @RequestMapping("/putsession")
    @ResponseBody
    public String putSession(HttpServletRequest request) {
        HttpSession session = request.getSession();
        log.info(session.getClass().toString());
        log.info(session.getId());
        String name = "fly";
        session.setAttribute("user", name);
        return "hello," + name;
    }
}

如果访问服务/putsession ,控制台输出为:
SpringSessionCrontroller : class org.apache.catalina.session.StandardSessionFacade
SpringSessionCrontroller : 1D8CC7826A3369BC33D867E4F4090D17

可以看到,Session 管理是通过Tomcat 提供的org.apache.catalina.session.StandardSessionFacade实现的。

在配置文件application.properties 中添加如下内容:
spring.session.store-type=RedislJDBCIHazelcastlnone

Spring Session 四种管理方式:

方式 含义
Redis Session数据存放在Redis中
JDBC Session数据存放在数据库中,session会自动创建相关表
Hazelcast Session数据存放在Hazelcast中
none 禁用Spring Session功能

通过配置属性spring.session.store-type 来指定Session 的存储方式,如:

spring.session.store-type=Redis

修改为配置和增加Spring Session 依赖后,如果访问服务/putsession,控制台输出为:
SpringSessionCrontroller: class org.springframework.session.web.http.SessionRepositoryFilter SessionRepositoryRequestWrapper S e s s i o n R e p o s i t o r y R e q u e s t W r a p p e r HttpSessionWrapper
SpringSessionCrontroller: d6fdfb46-841c-4514-8c74-613ddba1a0a5

4、使用Redis

本文将使用Redis来保存Session,需自行安装Redis
application.properties配置如下:

#Redis服务器地址
spring.redis.host=127.0.0.1
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=
#Session保存在Redis里
spring.session.store-type=Redis

pom.xml需要增加相关依赖如下:

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
    <groupId>org.springframework.sessiongroupId>
    <artifactId>spring-session-data-redisartifactId>
dependency>

再次访问/putsession后,我们通过Redis 客户端工具访问Redis ,比如使用redis-cli输入命令查看session

5、验证

本文使用的是Spring Boot 2.0.4.RELEASE、JDK 8、Nginx、Redis 环境。

如果Nignx和redis都已经启动并按上述配置好,假设我们在本机上部署两个Spring Boot应用端口分别是9000和9001,进入工程目录, 运行mvn package给项目打包,如项目jar打好后为springSession-0.0.1-SNAPSHOT.jar 在此目录打开命令窗口运行如下命令:

java -jar target/springSession-0.0.1-SNAPSHOT.jar --server.port=9000

打开另外一个命令窗口,进入工程目录, 运行:

java -jar target/springSession-0.0.1-SNAPSHOT.jar --server.port=9001

这时候, 我们就有两台Spring Boot 应用。接下来,我们访问以下地址, 并刷新多次:

http://127.0.0.1/putsession

这时候就看到两个Spring Boot 应用均有日志输出,比如9000 端口的应用控制台输出如下:

SpringSessionCrontroller:class org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper
SpringSessionCrontroller:d6fdfb46-841c-4514-8c74-613ddba1a0a5

9001 端口的Spring Boot 应用也有类似输出:

SpringSessionCrontroller:class org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper
SpringSessionCrontroller:d6fdfb46-841c-4514-8c74-613ddba1a0a5

我们看到,两个Spring Boot 应用都具有相同的sessionId ,如果停掉任意一台应用, 系统还有另外一台服务器提供服务, 会话信息保存在Redis 中。

你可能感兴趣的:(Spring Boot2.x+Redis实现SpringSession一致性)