在集群项目中,实现 Session 共享的方案

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

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

boot版本 2.0.6
nginx
redis

新建Boot项目

pom.xml

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

        <!--redis 配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--redis session 共享-->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

application.yml

server:
  port: 13002
  servlet:
    context-path: /projecsession
spring:
  session:
    store-type: redis #session的存储方式
  redis:
    host: 127.0.0.1
    port: 6379
    password: redis

简单代码

@GetMapping("/login")
    public String login(HttpServletRequest request, String name) {
        request.getSession().setAttribute(name, request.getSession().getId());
        return "这是13001端口 :" + request.getSession().getId();
    }

    @GetMapping("/getSession")
    public String getSession(HttpServletRequest request,String name) {
        return  "这是13001端口 :"+ request.getSession().getAttribute(name);
    }

新建一个项目(代码相同,只是端口不一样 13002)

将2个项目打成jar包并发布

启动脚本

#!/bin/bash
server_name=`ls *.jar`
echo $server_name

java -server -jar ./$server_name >> ${server_name}.out 2>&1 &

 

配置Nginx

修改 nginx.conf文件 并重新启动 ./nginx -s reload

# 配置集群 backServer 集群名字 随意定义 weight 分配权重
    upstream backServer { 
        server 127.0.0.1:13001 weight=1;
        server 127.0.0.1:13002 weight=1;
    }


    server {
        listen       80;
        server_name  test.yu.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location ^~/projecsession  {
            proxy_pass http://backServer;
            proxy_set_header Host                $host;
                        # 此配置使得服务端可以获取客户端真实ip
            proxy_set_header X-Real-IP           $remote_addr;
            proxy_set_header X-Forwarded-For     $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto   $scheme;

upstream 表示配置上游服务器
backServer 表示服务器集群的名字,这个可以随意取名字
upstream 里边配置的是一个个的单独服务
weight 表示服务的权重,意味者将有多少比例的请求从 Nginx 上转发到该服务上
location 中的 proxy_pass 表示请求转发的地址,/ 表示拦截到所有的请求,转发转发到刚刚配置好的服务集群中

语法形式

location   [ = | ~ | ~* | ^~ | @]   /uri/     { configuration }

匹配模式及顺序

匹配字符串分为两种:普通字符串(literal string)和正则表达式(regular expression),其中 ~ 和 ~* 用于正则表达式, 其他前缀和无任何前缀都用于普通字符串。

匹配顺序是:1、先匹配普通字符串,将最精确的匹配暂时存储;2、然后按照配置文件中的声明顺序进行正则表达式匹配,只要匹配到一条正则表达式,则停止匹配,取正则表达式为匹配结果;3、如果所有正则表达式都匹配不上,则取1中存储的结果;4、如果普通字符串和正则表达式都匹配不上,则报404 NOT FOUND。

location   =   /uri         =开头表示精确前缀匹配,只有完全匹配才能生效。

location   ^~   /uri        ^~开头表示普通字符串匹配上以后不再进行正则匹配。

location   ~   pattern     ~开头表示区分大小写的正则匹配。

location   ~*   pattern    ~*开头表示不区分大小写的正则匹配。

location   /uri                  不带任何修饰符,表示前缀匹配。

location   /                       通用匹配,任何未匹配到其他location的请求都会匹配到。

注意:正则匹配会根据匹配顺序,找到第一个匹配的正则表达式后将停止搜索。普通字符串匹配则无视顺序,只会选择最精确的匹配。

测试

springboot session实现在线用户 springboot springsession_正则表达式

springboot session实现在线用户 springboot springsession_正则表达式_02

springboot session实现在线用户 springboot springsession_正则表达式_03

springboot session实现在线用户 springboot springsession_spring_04

页面可见 Seesion共享实现了,看一下Redis的数据

springboot session实现在线用户 springboot springsession_正则表达式_05