談一談分佈式會話

一、什麼是會話

會話Session代表的是客戶端與服務器的一次交互過程,這個過程可以是連續也可以是時斷時續的。曾經的Servlet時代(jsp)),一旦用戶與服務端交互,服務器tomcat就會爲用戶創建一個session,同時前端會有一個jsessionid,每次交互都會攜帶。如此一來,服務器只要在接到用戶請求時候,就可以拿到jsessionid,並根據這個ID在內存中找到對應的會話session,當拿到session會話後,那麼我們就可以操作會話了。會話存活期間,我們就能認爲用戶一直處於正在使用着網站的狀態,一旦session超期過時,那麼就可以認爲用戶已經離開網站,停止交互了。用戶的身份信息,我們也是通過session來判斷的,在session中可以保存不同用戶的信息。session的使用之前在單體部分演示過,代碼如下∶

@GetMapping("/setSession")
public Object setSession(HttpServletRequest request) {
    HttpSession session = request.getSession();
    session.setAttribute("userInfo","new user");
    session.setMaxInactiveInterval(3600);
    session.getAttribute("userInfo");
    // session.removeAttribute("userInfo");
    return "ok";
}

二、無狀態會話

HTTP請求是無狀態的,用戶向服務端發起多個請求,服務端並不會知道這多次請求都是來自同一用戶,這個就是無狀態的。cookie 的出現就是爲了有狀態的記錄用戶。
常見的,ios與服務端交互,安卓與服務端交互,前後端分離,小程序與服務端交互,他們都是通過發起http來調用接口數據的,每次交互服務端都不會拿到客戶端的狀態,但是我們可以通過手段去處理,比如每次用戶發起請求的時候攜帶一個userid或者user-token,如此一來,就能讓服務端根據用戶id或token來獲得相應的數據。每個用戶的下一次請求都能被服務端識別來自同一個用戶。

三、有狀態會話

Tomcat中的會話,就是有狀態的,一旦用戶和服務端交互,就有會話,會話保存了用戶的信息,這樣用戶就"有狀態"了,服務端會和每個客戶端都保持着這樣的一層關係,這個由容器來管理(也就是tomcat),這個session會話是保存到內存空間裏的,如此一來,當不同的用戶訪問服務端,那麼就能通過會話知道誰是誰了。tomcat 會話的出現也是爲了讓http請求變的有狀態。如果用戶不再和服務端交互,那麼會話超時則消失,結束了他的生命週期。如此一來,每個用戶其實都會有一個會話被維護,這就是有狀態會話。
場景∶在傳統項目或者jsp項目中是使用的最多的session都是有狀態的,session的存在就是爲了彌補http的無狀態。

  • 注∶tomcat會話可以通過手段實現多系統之間的狀態同步,但是會損耗一定的時間,一旦發生同步那麼用戶請求就會等待,這種做法不可取。

五、單Tomcat會話(圖)

先來看一下單個tomcat會話,這個就是有狀態的,用戶首次訪問服務端,這個時候會話產生,並且會設置jsessionid放入cookie中,後續每次請求都會攜帶jsessionid以保持用戶狀態。

六、動靜分離會話(圖)

用戶請求服務端,由於動靜分離,前端發起http請求,不會攜帶任何狀態,當用戶第一次請求以後,我們手動設置一個token,作爲用戶會話,放入redis中,如此作爲redis-session,並且這個token設置後放入前端cookie中(app或小程序可以放入本地緩存),如此後續交互過程中,前端只需要傳遞token給後端,後端就能識別這個用戶請求來自誰了。

七、集羣分佈式系統會話(圖)

集羣或分佈式系統本質都是多個系統,假設這個裏有兩個服務器節點,分別是AB系統,他們可以是集羣,也可以是分佈式系統,一開始用戶和A系統交互,那麼這個時候的用戶狀態,我們可以保存到redis中,作爲A系統的會話信息,隨後用戶的請求進入到了B系統,那麼B系統中的會話我也同樣和redis關聯,如此AB系統的session就統一了。當然cookie是會隨着用戶的訪問攜帶過來的。那麼這個其實就是分佈式會話,通過redis來保存用戶的狀態。

八、類似關係∶局部變量與全局變量

Tomcat會話相當於一個類中某個方法的局部變量,只能在當前方法中使用;分佈式會話相當於一個類中的公用全局變量,可以被類中諸多方法使用。如下代碼∶

public class DistributedClusterTest {

    public String distributedSession ="global-1001";

    public void userSystem() {
        String userSession = "user-2001";

        System.out.println(distributedSession);
        System.out.printLn(orderSession);
    }

    public void orderSystem() {
        String orderSession = "order-3001";

        System.out.println(distributedSession);
        System.out.println(userSession);
    }
}

distributedSession是這個類中的全局變量,可以在其他的方法中被使用到,而 userSessionorderSession 是在方法中的局部變量,局部變量只能在本方法中使用,全局變量可以在其他方法裏都能使用。那麼分佈式會話和單個tomcat會話其實也是一樣的道理。

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