Distributed session for SpringBoot application

  redis, spring-session, springboot

SpringBoot application series articles

Order

This article focuses on how to build distributed sessions in spring boot applications. For distributed applications, the user’s Session management usually has four ways: Session Stick, Session copy, session centralized management and cookie-based management. Each review:

  • Session Stick

Need a user’s session and a server want to bind, a little coupling

  • Session replication

Each server has all the session information, session synchronization takes time, and it is also a problem that each server has all the data.

  • Session centralized management

Separate session service does not need synchronization, but also has network overhead, and also needs to deal with single-point problems.

  • Cookie-based management

Putting session data in cookie increases network load, and there are also security problems.
This paper focuses on centralized Session. There are mainly two schemes for its implementation. One is container-related, such as tomcat-redis-session-manager based on Tomcat and jetty-session-redis based on Jetty. The other is container decoupling, which is Spring-Session to be integrated today.

Configure redis cluster

Refer to my previous articleDocker Builds redis Cluster

New project

图片描述

Properties

#1.3.0.RELEASE以后的版本使用
server.session.timeout=10
#server.session-timeout=10 #1.2.7.RELEASE以及之前的版本使用
spring.redis.host=192.168.99.100 #这个就是docker machine default虚拟机的ip
#spring.redis.password=secret
spring.redis.port=6379

Test Controller

@RestController
@RequestMapping("/session")
public class HelloController {

    @RequestMapping("/uid")
    String uid(HttpSession session) {
        UUID uid = (UUID) session.getAttribute("uid");
        if (uid == null) {
            uid = UUID.randomUUID();
        }
        session.setAttribute("uid", uid);
        return session.getId();
    }
}

Start up

Accesshttp://localhost:8080/session/uid

d1b1cc0c-519e-431a-973c-6c742a014660

See redis

docker@default:~$ docker exec -it redis-master /bin/bash
root@86784a615b3d:/data# redis-cli keys '*'
1) "spring:session:sessions:d1b1cc0c-519e-431a-973c-6c742a014660"
2) "spring:session:expirations:1453639380000"

Equivalent to

SADD spring:session:expirations:<expire-rounded-up-to-nearest-minute> <session-id> 
EXPIRE spring:session:expirations:<expire-rounded-up-to-nearest-minute> 1800

Expirations:1453639380000 indicates that the session will be deleted at 1453639380000.
1800 means 1800 seconds, i.e. 30 minutes, which expires by default.

Look at the session object.

127.0.0.1:6379> hkeys spring:session:sessions:d1b1cc0c-519e-431a-973c-6c742a014660
1) "sessionAttr:uid"
2) "lastAccessedTime"
3) "maxInactiveInterval"
4) "creationTime"
127.0.0.1:6379> hget spring:session:sessions:d1b1cc0c-519e-431a-973c-6c742a014660 sessionAttr:uid
"\xac\xed\x00\x05sr\x00\x0ejava.util.UUID\xbc\x99\x03\xf7\x98m\x85/\x02\x00\x02J\x00\x0cleastSigBitsJ\x00\x0bmostSigBitsxp\xa0E\xe3\x1d\xf9K\xecW6\xcf\xbc\xfbU\x13M\x88"
127.0.0.1:6379> hget spring:session:sessions:d1b1cc0c-519e-431a-973c-6c742a014660 lastAccessedTime
"\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01Rs\x8d\x12b"

It has expired after 30 minutes.

127.0.0.1:6379> hget spring:session:sessions:d1b1cc0c-519e-431a-973c-6c742a014660 creationTime --raw
(error) ERR wrong number of arguments for 'hget' command
127.0.0.1:6379> keys *
(empty list or set)

Refresh the web page again to get a new sessionid.

3ed21473-c5ee-41e1-b64e-35b0737c0365

Problem

The timeout setting did not take effect. It was all based on 1800 seconds. It has been proved that this setting is only effective:

@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 60) //1分钟失效