1. 程式人生 > >CAS5.2x單點登入(八)---------客戶端叢集單點退出方式

CAS5.2x單點登入(八)---------客戶端叢集單點退出方式

上篇部落格已經說了單點退出是怎麼實現的,同時也留下了隱患,就是在叢集下的客戶端可能出現退出概率有效。而導致這個結果的就是因為我們客戶端無法根據服務端傳過來的st來找到相應的session,所以就無法清空。在最早之前,我們沒有考慮到叢集和分散式的時候,我們是這樣來使用cas和客戶端的互動
這裡寫圖片描述
我們通過cas提供的客戶端核心包來進行cas伺服器和cas客戶端的通訊。而在一系列的校驗通過後,cas會為客戶端生成session,而這個session也是保留在客戶端的記憶體中,這就是最早期的結構,對於這種方式下的cas是不會出現退出失敗的,因為你的session和st是唯一的,也只有一個客戶端,所以只要客戶端能收到服務端退出的訊息,就能退出成功。
但是當我們系統的流量越來越多的時候,我們發現一個伺服器頂不住流量的壓力的時候,我們應該怎麼辦呢,這時候我們一定是要進行叢集。

既然說到叢集,那麼我就簡單的介紹下叢集和分散式的區別:
叢集:同一個業務,部署在多個伺服器上(是不是很簡單)。
分散式:一個業務分拆多個子業務,部署在不同的伺服器上。
而我們針對上面的來說就是要進行叢集化了,尤其是針對微服務系列,你可以根據哪些服務訪問的流量大,而相應的增加微服務的叢集數量。而叢集和分散式都要考慮的問題就是session的共享問題,這個可是很頭疼的問題?不過好歹現在市面上有好多方法解決這個問題,用的最多的就是redis來共享session,就是將session存到redis中,不同的叢集下帶來的sessionid是相同的,通過sessionid去redis判斷是否存在這個session,通過這種方式來達到叢集的session共享。同時我們的互動方式就演變成這樣了。
這裡寫圖片描述

這樣就可以達到我們服務叢集的部署,同時也可以有效的減輕單個伺服器的壓力。
說了這麼多好像沒有講關於叢集退出的方式(馬上就開始講)。
上面已經說了對於叢集方式來說我們是使用redis來共享session的,所以這個時候對於我們單點退出的伺服器來說,cas客戶端的session是存在redis中的,所以我們銷燬他直接可以通過設定redis的sessison的某個引數來銷燬他。
如果在自己的頁面傳進來進行退出的話就好辦,好辦在與你能拿取到sessionid,然後在去銷燬他,但是單點退出的原理我上篇部落格已經說了,他並不是你一一操作每個客戶端進行退出的,那麼不是這樣的話,就無法帶著sessionid來進行session的銷燬。我們的單點退出是通過cas服務端的logout來觸發客戶端的退出(下節講解下cas服務端退出的原始碼),而服務端是不知道你每一個sessionId的,可能有的人說,那麼我們可以在cas服務端儲存每一個客戶端的id,但是你想過沒有,cas客戶端的session生成的時候是在什麼時候?你如果知道這個過程你就不會想這個方法。
我們知道服務端在退出的時候,是發出如下格式的請求
這裡寫圖片描述


上面的格式中有個叫sessionindex的東西,而這個東西就是st,服務端會將每一個登入成功後的客戶端的st票據給快取下來,然後退出的時候會將st傳送到客戶端。客戶端根據這個票據來尋找相應的session來進行退出。而我們客戶端在儲存session的時候會將st和session儲存到map中,st做為key,session做為value,然後退出的時候可以根據服務端傳過來的key來找value並進行銷燬。通過上面的流程我們可以在st做文章,這個時候我們可以修改cas提供的客戶端核心包,我們自己手動將st和sessionid存到redis中。

在普通的java程式下,我們也可以不這樣搞,通過叢集的廣播,什麼意思呢?就是在web.xml中我們配置客戶端叢集的伺服器地址,然後在cas伺服器退出的請求,判斷傳過來的st票據能否找到對應的session,如果找不到的話,那麼一定不再這個客戶端中,那麼就進行廣播,知道找到這個st的value為止,然後取銷燬他,這種確實是一種方法。網上也有這種方式,但是我還沒試驗過這種方式,但是理論上是可以的。還有一種方式就是使用nginx中的iphash,將相同的ip路由到同一個伺服器,這個也能達到要求。不過不建議這樣搞

我的方式是將st和sessionid存到redis中(修改原始碼的),然後在退出的時候,我會根據st去map中查詢,如果沒有找到的話,那麼就不在這個客戶端中,那麼我就通過redis來查詢這個sessionid並取出,然後在進行銷燬,同時刪除快取的st來達到叢集的單點退出。
可能這篇文章沒有給你們程式碼事例,這篇文章主要是給大家一個解決方案的思路,而我們的程式碼是需要在原始碼裡面修改的,所以可以檢視下一節的原始碼講解,下一節會貼上解決的程式碼