SpringBoot利用Redis管理分佈式Session

前言

由於Http連接是無狀態的,所以使用Tomcat做服務器的時候Tomcat內部會維護一個叫做Session的東東用來保存客戶端的狀態,一般情況下每個客戶端都有一個cookie裏面保存着叫jsessionid的cookie,每次訪問tomcat的時候都會攜帶上,Tomcat可以根據這個jsessionid找到對應的session。就像你去超市買東西,門口的儲物櫃可以視作一個session容器,而打出的二維碼條就是cookie。
在分佈式系統中,對於同一個客戶端,訪問哪個Tomcat服務器就會在哪個Tomcat裏面創建session。簡單來說我做一個登錄功能,即第一次訪問Tomcat的時候需要輸入用戶名密碼,訪問成功後就在自己的sesison裏面寫入用戶名,那麼我下次訪問的時候直接檢測session裏是否有自己的用戶名來判斷自己是否處於登錄狀態了。現在問題來了,如果我第一次訪問的是TomcatA,登錄成功後由於nginx的負載均衡第二次訪問打到了TomcatB上,那麼TomcatB裏面並沒有我的用戶名信息,所以我還需要重新登錄。一個最直觀的想法就是把TomcatA和TomcatB的session抽出來放到某一個位置,這樣不管訪問TomcatA還是TomcatB都會從同一個Session裏面獲取用戶信息。
SpringBoot以一個非常簡潔易用的方式幫我們實現了分佈式Session,我們需要做的僅僅是1個註解,幾行配置,幾行代碼。

一、配置maven

 

<dependencies>
    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <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>
</dependencies>

二、配置application.yml

 

spring:
  session:
    store-type: redis
    timeout: 3600s
    redis:
      flush-mode: on_save
      namespace: spring:session
  redis:
    host: 192.168.99.100
    port: 6379
    timeout: 5000ms

三、使用

 

//主類首先開啓EnableRedisHttpSession註解
@SpringBootApplication
@EnableRedisHttpSession
public class DistributeSessionApplication {

    public static void main(String[] args) {
        SpringApplication.run(DistributeSessionApplication.class, args);
    }
}

 

//編寫controller,set用於向session添加屬性,get用於從session獲取屬性
package com.example.distributesession.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

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

/**
 * @Author: 小混蛋
 * @CreateDate: 2018/12/11 17:20
 */
@RestController
public class TestController {

    @GetMapping("/set")
    public void test(HttpServletRequest request){
        request.getSession().setAttribute("message",request.getQueryString());
    }
    @GetMapping("/get")
    public Map<String,Object> two(HttpServletRequest request){
        Map<String,Object> map = new HashMap<>();
        map.put("sessionId",request.getSession().getId());
        map.put("message",request.getSession().getAttribute("message"));
        return map;
    }
}

四、複製項目

複製項目,設置端口爲8081,
訪問8080端口的接口/set,添加queryStirng爲name='xxx'

 

image.png

 

然後訪問8081端口的接口/get,結果如下

 

結果

五、原理淺析

本質上利用Tomcat的Filter的實現類SpringSessionRepositoryFilter實現了對每一次請求的攔截,攔截之後把Session放到Redis裏面

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章