天天看點

SpringBoot開發案例之分布式叢集共享Session

SpringBoot開發案例之分布式叢集共享Session

前言

在分布式系統中,為了提升系統性能,通常會對單體項目進行拆分,分解成多個基于功能的微服務,如果有條件,可能還會對單個微服務進行水準擴充,保證服務高可用。

那麼問題來了,如果使用傳統管理 Session 的方式,我們會遇到什麼樣的問題?

案例

這裡拿下單舉例,使用者小明在天貓上相中了一個的娃娃,覺得不錯,果斷購買,選尺寸,挑身高,然後确認選擇,趕緊送出訂單,然後就跳轉到了登入頁面!小明表示很郁悶,大寫的問号???

  • 小明進入娃娃頁面,此時請求通過代理服務發送到業務系統一。
  • 小明選尺寸,挑身高,此操作并沒有對後端服務發送請求。
  • 小明送出訂單,此時請求通過代理服務發送到業務系統二,然鵝,二系統此時并沒有查詢到小明的登入資訊,就被無情的跳轉到登入頁了。

方案

SpringBoot開發案例之分布式叢集共享Session

HttpSession 預設使用記憶體來管理 Session,通常服務端把使用者資訊存儲到各自的 Jvm 記憶體中。是以小明下單的時候找不到登入資訊,那麼我麼何不把使用者資訊集中存儲!?

為了測試效果,這裡我們搭建一個示範案例,項目涉及 SpringBoot、spring-session、redis、nginx 等相關元件。

pom.xml引入依賴:

<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>           

配置 redis 參數,軟體自行安裝:

## redis
#session存儲類型
spring.session.store-type=redis
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123456
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.timeout=3000           

簡單的使用者登入實作,省略部分代碼:

@RequestMapping(value="login",method=RequestMethod.POST)
public Result login(String username,String password,HttpServletRequest request,HttpServletResponse response) throws Exception {
        SysUser user = userService.getUser(username);
        if(user==null) {
            return Result.error("使用者不存在");
        }else {
            if(user.getPassword().equals(password)) {
                request.getSession().setAttribute("user", user);
                return Result.ok();
            }else {
                return Result.error("密碼錯誤");
            }
        }
}           

配置代理實作,基于 Nginx:

server {
        listen       80;
        server_name  blog.52itstyle.vip;
        location / {
            proxy_pass http://192.168.1.2:8080; 
        }
        location /cart {
             proxy_pass http://192.168.1.3:8080$request_uri;
        }
       location /order {
             proxy_pass http://192.168.1.4:8080$request_uri;
        }
  }
           

配置成功後登入系統,在 redis 中查詢使用者資訊:

127.0.0.1:6379> keys *
1) "spring:session:expirations:1562577660000"
2) "spring:session:sessions:1076c2bd-95b1-4f23-abd4-ab3780e32f6f"
3) "spring:session:sessions:expires:1076c2bd-95b1-4f23-abd4-ab3780e32f6f"           

小結

這樣,小明就可以開心的買娃娃了!