Redis realizes Session sharing

1. Use Redis to realize Session sharing

In the microservice architecture, multiple microservices often support the front-end requests. If the user status is involved, the distributed Session management problem needs to be considered. For example, if the user login request is distributed to server A and the user purchase request is distributed to server B, then the server must be able to obtain the user login information, otherwise normal transactions will be affected. Therefore, in the distribution Under the architecture of type B or microservice, it must be ensured that after the Session is saved on one application server, other application servers can synchronize or share the Session

2. At present, the mainstream distributed Session management consists of two schemes

  • Session replication

    Some Web servers can support Session replication, such as Tomcat. By modifying the configuration file of the Web server, the user allows the Web server to store Session data, and keeps the Session data of each Web server node consistent

    The implementation of this scheme depends on Web server, which needs Session replication function. When the number of sessions in web applications is large, each server node needs a part of memory to store sessions, which will take up a lot of memory resources. At the same time, a large number of Session objects are copied through network transmission, which not only takes up network resources, but also causes program running errors due to replication synchronization delay

    In the microservice architecture, N servers are often needed to support services together. This scheme is not recommended

  • Session centralized storage

    Use caching technology on a separate server or cluster with me, such as Redis to store Session data, manage all sessions centrally, and all Web servers obtain corresponding sessions from this storage medium. It is to continue Session sharing, and peel Session information out of the application, so as to achieve stateless service, which is convenient for rapid business development Horizontal expansion

    Under the microservice architecture, this scheme is recommended

3.Session sharing

1. What is Session

Because HTTP is a stateless protocol, when the server needs to record the user status, it needs to use some mechanism to identify the specific user. Session is another mechanism for accumulating customer records. The difference is that cookies are kept in the client browser, while sessions are kept on the server. When the client browser accesses the server, the server records the client information on the browser in some form, which is session. When the client browser accesses again, it only needs to find the user status from the session

2. Why Session sharing is needed

In the Internet industry, the number of users is huge, and multiple nodes are often required to provide a service together, as shown in the following figure:

The user's request will first arrive at the front gateway. The front gateway will distribute the request to the back-end server according to the routing policy. The first request will be sent to server A for processing. The next request may be processed by server B. If Session sharing is not done, the user may log in at service A. the next time the request arrives at server B, the user will log in again

In front gateway, we usually use lvs, Nginx or F5 and other software and hardware. Some software can specify policies to let users distribute their requests to the same server every time, which also has a disadvantage. If one of the services is Down, a batch of user transactions will fail. In practical work, we suggest using external cache devices to share Session to avoid the impact of single node hanging up on services. After using external cache Session, our shared data will be placed in external cache container, and the service itself will become stateless service, which can be increased or reduced according to the size of traffic at will.

Spring officially provides a special component Spring Session for Session management, which is very convenient to integrate distributed sessions in projects.

3.Spring Session

Spring Session provides a set of solutions for creating and managing servlet httpsessions. Spring Session provides the function of Clustered Sessions. By default, the external Redis is used to store Session data, so as to solve the problem of Session sharing.

Spring Session brings innovation to Session management of enterprise Java applications, making the following functions easier to implement:

  • API and Implementation for managing user session;
  • HttpSession, which allows to replace HttpSession in an application container (Tomcat) neutral way;
  • Unload the saved state of Session to specific external Session storage, such as Redis or Apache Geode, which can provide high-quality cluster in a way independent of application server;
  • Support multiple sessions on each browser, so as to easily build a richer end-user experience;
  • Control how Session ID is exchanged between client and server, so it is easy to write Restful API, because it can get Session ID from HTTP header information without relying on cookie;
  • When users use WebSocket to send requests, they can keep HttpSession active.

It is important to note that the core project of Spring Session does not rely on the Spring framework, so we can even apply it to projects that do not use the Spring framework.

4. Rapid integration

Introduce dependency package

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

Add profile

# Database configuration

spring.datasource.driverClassName=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/day1122?useUnicode=true&characterEncoding=utf8

spring.datasource.username=root

spring.datasource.password=root
# Show run SQL
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

#module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
## Custom log printing
#logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
##Log output to console
#appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
## Using the logging system to record sql
##appender=com.p6spy.engine.spy.appender.Slf4JLogger
## Set up p6spy driver agent
#deregisterdrivers=true

# Set encoding type
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.messages.encoding=UTF-8

# Redis database index (default is 0)
spring.redis.database=0
# Redis server address
spring.redis.host=localhost
# Redis server connection port
spring.redis.port=6379
# Redis server connection password (empty by default)
spring.redis.password=123
# Connection pool maximum connections (negative for no limit) default 8
spring.redis.lettuce.pool.max-active=8
# Connection pool maximum block wait time (use a negative value to indicate no limit) default -1
spring.redis.lettuce.pool.max-wait=
# Maximum free connections in connection pool default 8
spring.redis.lettuce.pool.max-idle=8
# Minimum free connections in connection pool default 0
spring.redis.lettuce.pool.min-idle=0

Create a config package in the project directory, create SessionConfig.java in the package, and write the configuration in the package

package com.jn.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

/**
 * @Author ScholarTang
 * @Date 2020/2/14 11:08 AM
 * @Desc Session Configuration class
 */

@Configuration
//maxInactiveIntervalInSeconds: set the Session expiration time. After using Redis Session,
//The server.session.timeout property in the original Spring Boot is no longer valid.
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400 * 30)
public class SessionConfig {
}

Complete the above two steps to configure the SpringBoot distributed Session

Verify Session sharing

1. Create a controller package in the project directory, create the SessionController.java class in the package, write two interfaces in the class, one is to generate session, the other is to obtain token.

2. copy the project, and then there are two visits

3. validation:

The authentication mode accesses the interface where service A generates session and obtains session, while service B accesses the interface where session is acquired. Compare whether the two different sessionids are the same. If they are the same, session sharing is realized

package com.jn.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author ScholarTang
 * @Date 2020/2/14 11:21 AM
 * @Desc Get / store Session
 */

@Slf4j
@RestController
public class SessionController {


    /**
     * TODO Set Session
     * @param request
     * @return
     */
    @RequestMapping("/setSession")
    public Map<String, Object> setSession(HttpServletRequest request) {
        Map<String, Object> map = new HashMap<>();
        request.getSession().setAttribute("sessionId",request.getRequestURL());
        map.put("request Url", request.getRequestURL());
        return map;
    }


    /**
     * TODO Get Session
     * @param request
     * @return
     */
    @RequestMapping("/getSession")
    public Map<String, Object> getSession(HttpServletRequest request) {
        Map<String, Object> map = new HashMap<>();
        map.put("sessionId", request.getSession().getId());
        map.put("message",request.getSession().getAttribute("message"));
        return map;
    }
}

Simulate login operation

Users log out and visit the home page

The user logs in (service A or service B may execute the request). Assuming that the login request is processed by service A, the session is successfully stored in the redis intermediate room, and then the request of the home page is processed by service B. the method of service B processing the home page obtains the session in the redis intermediate room. If the obtained session is not an interface, the corresponding data of the home page is obtained. No Then return the corresponding prompt information

package com.jn.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jn.domain.Admin;
import com.jn.service.AdminService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author ScholarTang
 * @Date 2020/2/14 11:44 AM
 * @Desc Handle user related business
 */

@Slf4j
@RestController
public class AdminController {

    @Autowired
    private AdminService service;


    /**
     * TODO Sign in
     * @param
     * @param request
     * @return
     */
    @PostMapping("/login")
    public String login (@RequestBody Admin admin,HttpServletRequest request) {
        String msg = "Login failed!";
        Admin dbAdmin = service.getOne(new LambdaQueryWrapper<Admin>().eq(Admin::getUsername,admin.getUsername()));
        if (dbAdmin != null) {
            if (admin.getPassword().equals(dbAdmin.getPassword())) {
                request.getSession().setAttribute("user",dbAdmin);
                Object user = request.getSession().getAttribute("user");
                if (user != null) {
                    System.out.println("session is ok");
                } else {
                    System.out.println("session is no");
                }
                msg = "Login succeeded!";
            }
        }
        return msg;
    }

    /**
     * TODO Sign out
     * @param request
     * @return
     */
    @RequestMapping("/loginOut")
    public String loginOut(HttpServletRequest request) {
        Object user = request.getSession().getAttribute("user");
        if (user != null) {
            System.out.println("session is ok");
        } else {
            System.out.println("session is no");
        }
        request.getSession().removeAttribute("user");
        return "Exit succeeded!";
    }

    @RequestMapping("/index")
    public String index(HttpServletRequest request) {
        String msg = "Dear! Please login first.";
        Object user = request.getSession().getAttribute("user");
        if (user != null) {
            msg = "This is the home page!";
        }
        return msg;
    }
}

Use Redis as the diagram after Session sharing:

As can be seen from the above figure, all services store the Session information in the Redis cluster, and both logout and update of the Session will be synchronized to the cluster to achieve the purpose of Session sharing.

summary

Under the microservice architecture, the system is divided into a large number of small and interrelated microservices, so it is necessary to consider the distributed Session management to facilitate the horizontal expansion of platform architecture upgrade. By introducing high-performance cache server into the architecture, sessions under the whole microservice architecture are managed uniformly.

Spring Session is an official Session management component provided by spring. It is integrated into the Spring Boot project to easily solve the problem of distributed Session management.

5. Code cloud address

https://gitee.com/Tang1314521/SpringSession.git

29 original articles published, 36 praised, 6069 visited
Private letter follow

Tags: Session Spring Redis encoding

Posted on Sun, 15 Mar 2020 04:29:22 -0400 by apollo