分散式系統session同步
阿新 • • 發佈:2019-01-07
分散式系統由於有多臺伺服器,使用者在一次會話裡有可能訪問不同的伺服器,這是由於每次請求都由負載均衡伺服器通過演算法去選擇訪問的伺服器。那裡使用者可能第一次訪問伺服器時web容器如tomcat新建了一個session儲存在了伺服器裡。再次訪問伺服器時可能就訪問另外一臺伺服器了就取不到這個session了。這會導致很對問題,例如有可能登入系統之後需要再次登入。
session是由首次訪問伺服器的時候,由web容器底層生成的session物件,由於儲存使用者的狀態資訊。同時會生成一個sessionId用於指向這個session物件,web容器(例如tomcat)以鍵值對的形式儲存這個session物件。然後伺服器將這個sessionId放在cookie裡返回給瀏覽器。再次請求伺服器就從cookie裡獲得sessionId然後從伺服器取得session物件。
多臺伺服器session同步解決方案
1.用redis儲存session,所有伺服器共享這個redis伺服器
HttpSession session = request.getSession();
Jedis redis = new Jedis("127.0.0.1");
String sessionJson = redis.get(session.getId());
if(StringUtils.isNotBlank(sessionJson)){
session=JSON.parseObject(sessionJson, HttpSession.class);
}else{
redis.set (session.getId(), JSON.toJSONString(session));
Cookie cookie = new Cookie("redisCookieId", session.getId());
response.addCookie(cookie);
}
2.使用瀏覽器cookie儲存session資訊
HttpSession session =request.getSession() ;
Cookie[] cookies = request.getCookies();
boolean isHasSession = false ;
String key = DESUtil.genDESKey();
for (Cookie cookie:cookies){
if(cookie.getName().equals("sessionInfo")){
session = JSON.parseObject(cookie.getValue(),HttpSession.class);
isHasSession=true;
}
}
if(!isHasSession){
String desSession = DESUtil.encode(JSON.toJSONString(session), key);
Cookie cookie = new Cookie("sessionInfo", desSession );
response.addCookie(cookie);
}
3.與使用redis類類似,使用一個共享資料庫,裡面新建一個專門儲存session資訊的表。
所有的伺服器要是使用session的話,直接從這個資料庫裡取session資訊。不過這種方式效率很低,並且需要隔斷時間去清理一些過期的session資料,高併發時,會有大量session進來,對資料庫效能要求較高。
4。對負載均衡伺服器分配伺服器演算法進行改進,同一使用者(即同一個sessionId)經過負載均衡分配伺服器時,預設分配上次訪問的伺服器。