SpringSession 簡單使用

楔子

學習筆記 ,做個記錄

session 共享問題解決

1 session複製

  • 優點

    tomcat 原生支持,只需要修改配置文件

  • 缺點

    1. session 同步需要數據傳輸,佔用大量網絡帶寬,降低了服務器羣的業務處理能力
    2. 任意一臺web-server保存的數據都是所有web-server的session總和,收到內存限制無法水平擴展更多的web-server
    3. 大型分佈式集羣情況下,由於所有web-server都全量保存數據,所有次方案不可取

2 hash一致性

  • 優點

    1. 只需要該nginx配置,不需要修改應用代碼
    2. 負載均衡,只要hash屬性的值分佈式均勻的,多臺web-server的負載是均衡的
    3. 可以支持web-server水平擴展(session同步是不行的,受內存限制)
  • 缺點

    1. session還是存在web-server中,所有web-server重啓可能導致session丟失,影響業務,如部分用戶需要重新登錄。
    2. 如果web-server水平擴展,rehash後的session重新分佈,也會有一部分用戶路由到不正確的session。

    以上的缺點問題不大,因爲session本來都是有有效期的。所有這兩種反向代理的方式可以使用。

3 統一存儲

  • 優點
    1. 沒有安全隱患
    2. 可以水平擴展,數據庫/緩存水平切分即可
    3. web-server重啓或擴容都不會丟失
  • 不足
    1. 增加了一次網絡調用,並且需要修改相應的代碼,如將所有的getSession方法替換爲從Redis查數據的方式,redis獲取數據比內存慢很多。
    2. 上面的缺點可以用springSession完美解決。

4 session共享問題解決-不同服務,子域session共享|(springSession)

SpringSession 簡單使用

在這裏插入圖片描述
以下使用Redis作爲存儲session的介質

1 pom引入依賴

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

2 使用註解開啓 springsession

# springboot啓動類加註解
@EnableRedisHttpSession

代碼中處理

@Slf4j
@RestController
@RequestMapping("/session")
public class SessionController {


    @RequestMapping("login")
    public String login(HttpServletRequest req, HttpServletResponse resp, HttpSession session,
                        User user) {
        //TODO 1 默認發的令牌,SESSION=*** ,作用域:當前域(解決子域共享)
        //TODO 2使用JSON的序列化存儲數據到 Redis
        log.info("login user is {}", user);
        session.setAttribute(SysUtils.LOGIN_NAME, user);
        return String.format("%s|%s|", SysUtils.getDateSpan(), user.getUname());
    }

    @RequestMapping("show")
    public Object showLoginUser(HttpSession session) {
        Object attribute = session.getAttribute(SysUtils.LOGIN_NAME);
        log.info("獲取的session user is {}", JSON.toJSONString(attribute));
        return attribute;
    }
}

設置Redis存儲爲JSON以及配置子域共享

@Configuration
public class SessionConfig {

    /**
     * 設置熱session cookie name 以及子域共享
     *
     * @return
     */
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();

        serializer.setCookieName("WEBJSESSIONID");
        serializer.setCookiePath("/");
        serializer.setDomainName("grq.com");
        //serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
        return serializer;
    }
    /**
     * 設置redis session 序列化方式爲JSON
     *
     * @return
     */
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        //return new FastJsonRedisSerializer();
        //return new GenericFastJsonRedisSerializer();
        return  new GenericJackson2JsonRedisSerializer();
    }
}

**域名和子域名使用Windows hosts模擬 **

3 配置文件

配置存儲方式爲redis,以及redis配置

################################ session
spring.session.store-type=redis
# more就是30分鐘
server.servlet.session.timeout=30m
################################ session |end
#redis
spring.redis.host=127.0.0.1
spring.redis.port=6379

Redis存儲
在這裏插入圖片描述
**域名 使用SwitchHosts! 添加模擬 **
在這裏插入圖片描述

遇到的問題

使用fastjson 作爲序列化 JSON的時候,出現了**NoSuchMethodError: com.alibaba.fastjson.serializer.JavaBeanSerializer.processValue**

https://github.com/alibaba/fastjson/issues/2780
需要升級 將fastjson從1.2.57升級到1.2.61

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