springboot 实现session共享(spring-sesion+nginx + redis)

一、Spring-Session使用的场景

HttpSession是通过Servlet容器进行创建和管理的,在单机环境中。通过Http请求创建的Session信息是存储在Web服务器内存中,如Tomcat/Jetty。假如当用户通过浏览器访问应用服务器,session信息中保存了用户的登录信息,并且session信息没有过期失,效那么用户就一直处于登录状态,可以做一些登录状态的业务操作。

但是现在很多的服务器都采用分布式集群的方式进行部署,一个Web应用,可能部署在几台不同的服务器上,通过LVS或者Nginx等进行负载均衡(一般使用Nginx+Tomcat实现负载均衡)。此时来自同一用户的http请求将有可能被分发到不同的web站点中去(如:第一次分配到A站点,第二次可能分配到B站点)。那么问题就来了,如何保证不同的web站点能够共享同一份session数据呢?

假如用户在发起第一次请求时候访问了A站点,并在A站点的session中保存了登录信息,当用户第二次发起请求,通过负载均衡请求分配到B站点了,那么此时B站点能否获取用户保存的登录的信息呢?答案是不能的,因为上面说明,session是存储在对应Web服务器的内存的,不能进行共享,此时spring-session就出现了,来帮我们解决这个session共享的问题!

 简单点说就是请求http请求经过Filter链,根据配置信息过滤器将创建session的权利由tomcat交给了spring-session中的SessionRepository,通过spring-session创建会话,Session的内容统一存储在一个数据库(如MySQL)或缓存(如Redis,Mongo)中。

当然使用Nginx的ip_hash策略也可以解决session同步的问题。

在使用Nginx的ip_hash策略时候,每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,这样就解决session的同步问题。

 二、代码实现

1、pom引包

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.zhouzy.redis</groupId>
  <artifactId>zhouzyRedis</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>zhouzyRedis</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.5.RELEASE</version>
	</parent>
    <!--修改jdk版本号-->
	<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

  <dependencies>
  	 <!-- web模块 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
  	<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.30</version>
	</dependency>
	<!-- 加解密工具 -->
	<dependency>
		<groupId>commons-codec</groupId>
		<artifactId>commons-codec</artifactId>
	</dependency>
	
	<!--使用Redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--借助guava的布隆过滤器-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>
	
		<dependency>
	        <groupId>org.springframework.session</groupId>
	        <artifactId>spring-session-data-redis</artifactId>
	    </dependency>
	
    <dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
  </dependencies>

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

2、application.yml

server:
  port:  8081
spring:
  redis:
    database: 3
    host: 127.0.0.1
    port: 6379
    jedis.pool.max-idle: 100
    jedis.pool.max-wait: -1ms
    jedis.pool.min-idle: 2
    timeout: 2000ms
  session:
    store-type:  redis

3、控制层接口

package com.zhouzy.redis.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class RedisSessionController {
 
    @RequestMapping("/show")
    public String show(HttpServletRequest request) {
         return "我是: " + request.getLocalPort();
    }
 
    @RequestMapping(value = "/session")
    public String getSession(HttpServletRequest request) {
        request.getSession().setAttribute("userName", "admin");
        return "I'm " + request.getLocalPort() + " ,save session " + request.getSession().getId();
    }

    @RequestMapping(value = "/get")
    public String get(HttpServletRequest request) {
        String userName = (String) request.getSession().getAttribute("userName");
        return "我是 " + request.getLocalPort() + " ,userName :" + userName;
    }
}

4、启动类

package com.zhouzy.redis;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Hello world!
 *
 */
@SpringBootApplication
public class WebApplication {
    public static void main( String[] args ){
       SpringApplication.run(WebApplication.class, args);
    }
}

三、测试

1、启动redis

启动停止命令:

redis-server --service-install redis.windows.conf
启动服务:redis-server --service-start
停止服务:redis-server --service-stop

2、启动Nginx

upstream  c{
    server localhost:8081;
    server localhost:8088;
}
server {
    listen       80;
    server_name  localhost;
    location / {
        proxy_pass http://zhouzy;
    }
 }

启动命令:

D:\SOFT\nginx-1.12.2>nginx.exe

停止:

停止:
D:\SOFT\nginx-1.12.2>nginx.exe -s stop或
D:\SOFT\nginx-1.12.2>nginx.exe -s quit

3、启动应用

1)先启动8081端口

2)修改端口号为8088,在启动一个

4、访问测试

http://localhost/session

 http://localhost/get

 在8088上保存的session,然后在8081和8088上都可以取到,实现了session共享!Nginx也实现了分流!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wwwzhouzy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值