使用Spring session实现分布式应用session共享 - Go语言中文社区

使用Spring session实现分布式应用session共享


Session与Cookie基础

由于http协议是无状态的协议,为了能够记住请求的状态,于是引入了Session和Cookie的机制。我们应该有一个很明确的概念,那就是Session是存在于服务器端的,在单体式应用中,他是由tomcat管理的,存在于tomcat的内存中,当我们为了解决分布式场景中的session共享问题时,引入了redis,其共享内存,以及支持key自动过期的特性,非常契合session的特性,我们在企业开发中最常用的也就是这种模式。但是只要你愿意,也可以选择存储在JDBC,Mongo中,这些,spring都提供了默认的实现,在大多数情况下,我们只需要引入配置即可。而Cookie则是存在于客户端,更方便理解的说法,可以说存在于浏览器。

代码示例

使用Springboot编写一个非常简单的服务端,来加深对其的理解。需求很简单,当浏览器访问localhost:8000/test/cookie?browser=xxx时,如果没有获取到session,则将request中的browser存入session;如果获取到session,便将session中的browser值输出。顺便将request中的所有cookie打印出来。
创建一个hellospring项目。

@Controller
public class CookieController {
    @RequestMapping("/test/cookie")
    public String cookie(@RequestParam("browser") String browser, HttpServletRequest request, HttpSession session) {
        //取出session中的browser
        Object sessionBrowser = session.getAttribute("browser");
        if (sessionBrowser == null) {
            System.out.println("不存在session,设置browser=" + browser);
            session.setAttribute("browser", browser);
        } else {
            System.out.println("存在session,browser=" + sessionBrowser.toString());
        }
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie : cookies) {
                System.out.println(cookie.getName() + " : " + cookie.getValue());
            }
        }
        return "index";
    }
}

使用Redis集成Spring Session

引入依赖,Spring Boot的版本采用1.5.6

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

配置类开启Redis Http Session

@Configuration
@EnableRedisHttpSession
public class HttpSessionConfig {
}

为了方便演示多节点之间的session共享,我们生成多个配置文件。
application.properties

spring.redis.host=172.17.0.61
spring.redis.port=7200
spring.redis.database=0
spring.application.name=hellospring

application-default.properties

server.port=8001

application-dev1.properties

server.port=8001

application-dev2.properties

server.port=8002

进入cmd模式,在项目执行mvn package。
分别启动dev1和dev2。

java -jar hellospring-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev1
java -jar hellospring-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev2

安装NGINX,将请求分发到两个不同节点,配置文件如下。

        listen      8000;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass http://localhost;  
            proxy_set_header Host $host;  
            proxy_set_header X-Real-IP $remote_addr;  
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        }
    upstream localhost{  
         #hash $remote_addr consistent;  
         server 127.0.0.1:8001 weight=1;  
         server 127.0.0.1:8002 weight=1;  
    } 

访问http://localhost:8000/test/cookie?browser=chrome,观察console输出内容。
这里写图片描述
可以看到session当中没有值,browser被保存到session中,查看redis,发现session数据已经被缓存到redis。
这里写图片描述
解析一下这个redis store。
​1 spring:session是默认的Redis HttpSession前缀(redis中,我们常用’:’作为分割符)。

2 每一个session都会有三个相关的key,第三个key最为重要,它是一个HASH数据结构,将内存中的session信息序列化到了redis中。如上文的browser,就被记录为sessionAttr:browser=chrome,还有一些meta信息,如创建时间,最后访问时间等。

3 另外两个key,expirations:1504446540000和sessions:expires:7079…我发现大多数的文章都没有对其分析,前者是一个SET类型,后者是一个STRING类型,可能会有读者发出这样的疑问,redis自身就有过期时间的设置方式TTL,为什么要额外添加两个key来维持session过期的特性呢?这需要对redis有一定深入的了解才能想到这层设计。当然这不是本节的重点,简单提一下:redis清除过期key的行为是一个异步行为且是一个低优先级的行为,用文档中的原话来说便是,可能会导致session不被清除。于是引入了专门的expiresKey,来专门负责session的清除,包括我们自己在使用redis时也需要关注这一点。在开发层面,我们仅仅需要关注第三个key就行了。

再次访问http://localhost:8000/test/cookie?browser=chrome
这里写图片描述
现在dev1也能正常访问到session内容。

代码位置:
https://github.com/39627020/experience/tree/master/java/springboot/hellospring

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/jzd1997/article/details/78060693
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-08 17:27:18
  • 阅读 ( 1695 )
  • 分类:Go应用

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢