分散式叢集Session共享 簡單多tomcat8+redis的session共享實現
阿新 • • 發佈:2019-01-01
什麼是Session/Cookie
使用者使用網站的服務,基本上需要瀏覽器與Web伺服器的多次互動。HTTP協議本身是無狀態的,當用戶的第一次訪問請求結束後,後端伺服器就無法知道下一次來訪問的還是不是上次訪問的使用者。我們需要基於HTTP協議支援會話狀態的機制,這樣的機制可以使Web伺服器從多次單獨的HTTP請求中知道哪些請求是來自哪個會話的。 Session與Cookie的作用都是為了保持訪問使用者與後端伺服器的互動狀態。理解Cookie Cookie的作用通俗的說就是當一個使用者通過HTTP協議訪問一個伺服器的時候,這個伺服器會將一些Key/Value鍵值對返回給客戶端瀏覽器,並給這些資料加上一些限制條件,在條件符合時這個使用者下次訪問這個伺服器的時候,資料又被完整地帶回給伺服器。理解Session叢集遇到的問題
當我們的應用伺服器變為多臺的時候就會遇到Session共享的問題。當我們第一次訪問網站的時候,負載均衡將本地的請求分配到Web伺服器1,那麼Session建立在Web伺服器1,第二次訪問的時候如果我們不做處理就不能保證還是會落到Web伺服器1了。解決叢集Session共享問題
1. Session Sticky
讓負載均衡器能夠根據每次的請求的會話標識來進行請求的轉發,這樣就能保證每次都能落到同一臺伺服器上面,這種方式稱為Session Sticky方式。如下圖:2. Session Replication
還是以吃飯的例子,如果我們在每個飯店都存放一套自己的碗筷,就可以自己的選擇去哪家吃飯了。這就是Session Replication。如下圖: 此方案不用再要求負載均衡器保證同一個會話的多次請求必須到同一個Web伺服器上了。我們在Web伺服器之間增加了會話資料的同步,通過同步就保證了不同Web伺服器之間Session資料的一致。一般應用容器都支援Session Replication方式,與Session Sticky方案相比,Session Replication方式對負載均衡器沒有那麼多的要求。 存在問題: 1. 同步Session資料造成了網路頻寬的開銷。只要Session資料有變化,就需要將資料同步到所有其他機器上,機器越多,同步帶來的網路頻寬開銷就越大。 2. 每臺Web伺服器都要儲存所有Session資料,如果整個叢集的Session資料很多(很多人同時訪問網站)的話,每臺機器用於儲存Session資料的內容佔用會很嚴重。 這個方案是靠應用容器來完成Session的複製從而解決Session的問題的,應用本身並不關心這個事情。這個方案不適合叢集機器數多的場景。如果只有幾臺機器,用這個方案是可以的。3. Session資料集中儲存
將Session資料集中儲存,然後不同Web伺服器從同樣的地方獲取Session,如下圖: Session資料不儲存到本機而且存放到一個集中儲存的地方,修改Session也是發生在集中儲存的地方。Web伺服器使用Session從集中儲存的地方讀取。這樣保證了不同Web伺服器讀取到的Session資料都是一樣的。儲存Session的具體方式可以是資料庫、分散式儲存系統等。這個方案解決了Session Replication方案中記憶體的問題,對於網路頻寬也比Session Replication要好。 存在問題: 1. 讀寫Session資料引入了網路操作,這相對於本機的資料讀取來說,問題就在於存在時延和不穩定性,不過我們的通訊基本都是發生在內網,問題不大。 2. 如果集中儲存Session的機器或者叢集有問題,就會影響到我們的應用。 相對於Session Replication,當Web伺服器數量比較大、Session數比較多的時候,這個集中儲存方案的優勢是非常明顯的。4. Cookie Based
這個方案對於同一個會話的不同請求也是不限制具體處理機器的。它是通過Cookie來傳遞Session資料的,如下圖: 從上圖可以看出,我們的Session資料放到Cookie中,然後在Web伺服器上從Cookie中生成對應的Session資料。這就好比我們每次都把自己的碗筷帶在身上,這樣去那家飯店就可以隨意選擇了。相對前面的集中儲存方案,不會依賴外部的儲存系統,也就不存在從外部系統獲取、寫入Session資料的網路時延、不穩定性了。 存在問題: 1. Cookie長度的限制。我們知道Cookie是有長度限制的,而這也會限制Session資料的長度。 2. 安全性。Session資料本來都是服務端資料,而這個方案是讓這些服務端資料到了外部網路及客戶端,因此存在安全性上的問題。我們可以對寫入的Cookie的Session資料做加密,不過對於安全來說,物理上不能接觸才是安全的。 3. 頻寬消耗。指的是我們資料中心的整體外部頻寬的消耗。 4. 效能影響。每次HTTP請求和響應都帶有Session資料,對Web伺服器來說,在同樣的處理情況下,響應的結果輸出越少,支援的併發請求就越多。生成Session資料也會影響處理速度。 這4個方案都是可用的方案,但是對於大型網站來說,Session Stick和Session資料集中儲存是比較好的方案,這兩個方案各有優劣,需要在具體的場景中做出選擇和權衡。以下我們對第三種方案Session資料集中儲存進行簡單的例子介紹簡單tomcat8+redis的session共享實現
1. 下載開源專案2. 建立maven專案 建立專案並把src/main/java/com/orangefunction/tomcat/redissessions/複製到專案3. 支援tomcat8需修改程式碼 RedisSessionManager.java@@ -713,9 +713,9 @@ private void initializeSerializer() throws ClassNotFoundException, IllegalAccess | ||
serializer = (Serializer) Class.forName(serializationStrategyClass).newInstance(); | serializer = (Serializer) Class.forName(serializationStrategyClass).newInstance(); | |
Loader loader =null; | Loader loader =null; | |
- | +Context context =this.getContext(); | |
- if (getContainer()!=null) { | + if (context!=null) { | |
- loader =getContainer().getLoader(); | + loader =context.getLoader(); | |
} | } | |
ClassLoader classLoader =null; | ClassLoader classLoader =null; |
public void doGet(HttpServletRequest request, HttpServletResponse response)參考網址: redis + Tomcat 8 的session共享解決 【http://www.cnblogs.com/interdrp/p/4868740.html 】 用Redis儲存Tomcat叢集的Session【http://blog.csdn.net/chszs/article/details/42610365 】 分散式集群系統下的高可用session解決方案【http://tendyming.iteye.com/blog/1815136 】 《大型網站系統與Java中介軟體實踐》 《深入分析Java Web技術內幕》code:
throws ServletException, IOException {
HttpSession session = request.getSession();
/*
// 1. 設定Session
for (int i = 0; i < 10; i++) {
session.setAttribute("name" + i, "session_data_" + i);
}
*/
// 2. 註釋第一步,重啟tomcat後看是否還可以讀取到Session
String str = "";
for (int i = 0; i < 10; i++) {
str = str + session.getAttribute("name" + i) + "<br>";
}
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println(str);
out.flush();
out.close();
// 訪問: http://localhost:8080/tomcat8_redis_session_web/servlet/TestRedisSessionServlet
}