分布式集群多個tomcat7+redis的session共享實(shí)現(xiàn)庆猫,科多大數(shù)據(jù)帶你來看看
什么是Session/Cookie
用戶使用網(wǎng)站的服務(wù),基本上需要瀏覽器與Web服務(wù)器的多次交互乍桂。HTTP協(xié)議本身是無狀態(tài)的锨苏,當(dāng)用戶的第一次訪問請求結(jié)束后公罕,后端服務(wù)器就無法知道下一次來訪問的還是不是上次訪問的用戶。我們需要基于HTTP協(xié)議支持會話狀態(tài)的機(jī)制容贝,這樣的機(jī)制可以使Web服務(wù)器從多次單獨(dú)的HTTP請求中知道哪些請求是來自哪個會話的自脯。
Session與Cookie的作用都是為了保持訪問用戶與后端服務(wù)器的交互狀態(tài)。
理解Cookie
Cookie的作用通俗的說就是當(dāng)一個用戶通過HTTP協(xié)議訪問一個服務(wù)器的時候斤富,這個服務(wù)器會將一些Key/Value鍵值對返回給客戶端瀏覽器膏潮,并給這些數(shù)據(jù)加上一些限制條件,在條件符合時這個用戶下次訪問這個服務(wù)器的時候茂缚,數(shù)據(jù)又被完整地帶回給服務(wù)器戏罢。
理解Session
Cookie可以讓服務(wù)端程序跟蹤每個客戶端的訪問,但是每次客戶端的訪問都必須傳回這些Cookie脚囊,如果Cookie很多龟糕,這無形地增加了客戶端與服務(wù)端的數(shù)據(jù)傳輸量,而Session的出現(xiàn)正是為了解決這個問題悔耘。
同一個客戶端每次和服務(wù)端交互時讲岁,不需要每次都傳回所有的Cookie值,而是只要傳回一個會話標(biāo)識(SessionId),這個ID是客戶端第一次訪問服務(wù)器的時候生成的缓艳,而且每個客戶端是唯一的校摩。這樣每個客戶端就有一個唯一的ID,客戶端只要傳回這個ID就行了阶淘,這個ID通常是NAME為JSESIONID的一個Cookie衙吩。在Web服務(wù)器上,各個會話獨(dú)立存儲保存不同會話的信息溪窒。如果遇到禁用Cookie的情況坤塞,一般的做法就是把這個會話標(biāo)識放到URL的參數(shù)中。
總結(jié)
Cookie和Session都是為了保持用戶訪問的連續(xù)狀態(tài)澈蚌,之所以要保持這種狀態(tài)摹芙,一方面是為了方便業(yè)務(wù)實(shí)現(xiàn),另一方面就是簡化服務(wù)端程序設(shè)計宛瞄,提高訪問性能浮禾。但也帶來了一些問題,如安全問題份汗、集群環(huán)境下Session同步問題等
集群遇到的問題
當(dāng)我們的應(yīng)用服務(wù)器變?yōu)槎嗯_的時候就會遇到Session共享的問題盈电。當(dāng)我們第一次訪問網(wǎng)站的時候,負(fù)載均衡將本地的請求分配到Web服務(wù)器1杯活,那么Session創(chuàng)建在Web服務(wù)器1挣轨,第二次訪問的時候如果我們不做處理就不能保證還是會落到Web服務(wù)器1了。
解決集群Session共享問題
1. Session Sticky
讓負(fù)載均衡器能夠根據(jù)每次的請求的會話標(biāo)識來進(jìn)行請求的轉(zhuǎn)發(fā)轩猩,這樣就能保證每次都能落到同一臺服務(wù)器上面,這種方式稱為Session Sticky方式荡澎。如下圖:
存在問題:
1. 如果這一臺Web服務(wù)器宕機(jī)或者重啟了均践,服務(wù)器上的會話數(shù)據(jù)會丟失,用戶需要重新登陸等摩幔。
2. 會話標(biāo)識是應(yīng)用層的信息彤委,那么負(fù)載均衡器要將同一個會話的請求都保存到同一個Web服務(wù)器上的話,就需要進(jìn)行應(yīng)用層的解析或衡,這個開銷比第四層交換(LVS負(fù)載均衡器屬于第四層)要大焦影。
3. 負(fù)載均衡器變?yōu)橐粋€有狀態(tài)的節(jié)點(diǎn),要將會話保存到具體的Web服務(wù)器的映射封断。和無狀態(tài)的節(jié)點(diǎn)相比斯辰,內(nèi)存消耗會更大,容災(zāi)方面會更麻煩坡疼。
打個比方彬呻,比如Web服務(wù)器是飯店,會話數(shù)據(jù)是碗筷。要保證每次吃飯都用自己的碗筷的話闸氮,我就把餐具存在某一家飯店剪况,并且每次都去這家店吃飯。
2. Session Replication
還是以吃飯的例子蒲跨,如果我們在每個飯店都存放一套自己的碗筷译断,就可以自己的選擇去哪家吃飯了。這就是Session Replication或悲。如下圖:
此方案不用再要求負(fù)載均衡器保證同一個會話的多次請求必須到同一個Web服務(wù)器上了孙咪。我們在Web服務(wù)器之間增加了會話數(shù)據(jù)的同步,通過同步就保證了不同Web服務(wù)器之間Session數(shù)據(jù)的一致隆箩。一般應(yīng)用容器都支持Session Replication方式该贾,與Session Sticky方案相比,Session Replication方式對負(fù)載均衡器沒有那么多的要求捌臊。
存在問題:
1. 同步Session數(shù)據(jù)造成了網(wǎng)絡(luò)帶寬的開銷杨蛋。只要Session數(shù)據(jù)有變化,就需要將數(shù)據(jù)同步到所有其他機(jī)器上理澎,機(jī)器越多逞力,同步帶來的網(wǎng)絡(luò)帶寬開銷就越大。
2. 每臺Web服務(wù)器都要保存所有Session數(shù)據(jù)糠爬,如果整個集群的Session數(shù)據(jù)很多(很多人同時訪問網(wǎng)站)的話寇荧,每臺機(jī)器用于保存Session數(shù)據(jù)的內(nèi)容占用會很嚴(yán)重。
這個方案是靠應(yīng)用容器來完成Session的復(fù)制從而解決Session的問題的执隧,應(yīng)用本身并不關(guān)心這個事情揩抡。這個方案不適合集群機(jī)器數(shù)多的場景。如果只有幾臺機(jī)器镀琉,用這個方案是可以的峦嗤。
3. Session數(shù)據(jù)集中存儲
將Session數(shù)據(jù)集中存儲,然后不同Web服務(wù)器從同樣的地方獲取Session屋摔,如下圖:
Session數(shù)據(jù)不保存到本機(jī)而且存放到一個集中存儲的地方烁设,修改Session也是發(fā)生在集中存儲的地方。Web服務(wù)器使用Session從集中存儲的地方讀取钓试。這樣保證了不同Web服務(wù)器讀取到的Session數(shù)據(jù)都是一樣的装黑。存儲Session的具體方式可以是數(shù)據(jù)庫、分布式存儲系統(tǒng)等弓熏。這個方案解決了Session Replication方案中內(nèi)存的問題恋谭,對于網(wǎng)絡(luò)帶寬也比Session Replication要好。
存在問題:
1. 讀寫Session數(shù)據(jù)引入了網(wǎng)絡(luò)操作硝烂,這相對于本機(jī)的數(shù)據(jù)讀取來說箕别,問題就在于存在時延和不穩(wěn)定性铜幽,不過我們的通訊基本都是發(fā)生在內(nèi)網(wǎng),問題不大串稀。
2. 如果集中存儲Session的機(jī)器或者集群有問題除抛,就會影響到我們的應(yīng)用。
相對于Session Replication母截,當(dāng)Web服務(wù)器數(shù)量比較大到忽、Session數(shù)比較多的時候,這個集中存儲方案的優(yōu)勢是非常明顯的清寇。
4. Cookie Based
這個方案對于同一個會話的不同請求也是不限制具體處理機(jī)器的喘漏。它是通過Cookie來傳遞Session數(shù)據(jù)的,如下圖:
從上圖可以看出华烟,我們的Session數(shù)據(jù)放到Cookie中翩迈,然后在Web服務(wù)器上從Cookie中生成對應(yīng)的Session數(shù)據(jù)。這就好比我們每次都把自己的碗筷帶在身上盔夜,這樣去那家飯店就可以隨意選擇了负饲。相對前面的集中存儲方案,不會依賴外部的存儲系統(tǒng)喂链,也就不存在從外部系統(tǒng)獲取返十、寫入Session數(shù)據(jù)的網(wǎng)絡(luò)時延、不穩(wěn)定性了椭微。
存在問題:
1. Cookie長度的限制洞坑。我們知道Cookie是有長度限制的,而這也會限制Session數(shù)據(jù)的長度蝇率。
2. 安全性迟杂。Session數(shù)據(jù)本來都是服務(wù)端數(shù)據(jù),而這個方案是讓這些服務(wù)端數(shù)據(jù)到了外部網(wǎng)絡(luò)及客戶端本慕,因此存在安全性上的問題逢慌。我們可以對寫入的Cookie的Session數(shù)據(jù)做加密,不過對于安全來說间狂,物理上不能接觸才是安全的。
3. 帶寬消耗火架。指的是我們數(shù)據(jù)中心的整體外部帶寬的消耗鉴象。
4. 性能影響。每次HTTP請求和響應(yīng)都帶有Session數(shù)據(jù)何鸡,對Web服務(wù)器來說纺弊,在同樣的處理情況下,響應(yīng)的結(jié)果輸出越少骡男,支持的并發(fā)請求就越多淆游。生成Session數(shù)據(jù)也會影響處理速度。
這4個方案都是可用的方案,但是對于大型網(wǎng)站來說犹菱,Session Stick和Session數(shù)據(jù)集中存儲是比較好的方案拾稳,這兩個方案各有優(yōu)劣,需要在具體的場景中做出選擇和權(quán)衡腊脱。
以下我們對第三種方案Session數(shù)據(jù)集中存儲進(jìn)行簡單的例子介紹
簡單tomcat8+redis的session共享實(shí)現(xiàn)
1. 下載開源項(xiàng)目
https://github.com/jcoleman/tomcat-redis-session-manager
2. 創(chuàng)建maven項(xiàng)目
創(chuàng)建項(xiàng)目并把src/main/java/com/orangefunction/tomcat/redissessions/復(fù)制到項(xiàng)目
3. 打包部署
將實(shí)現(xiàn)包和依賴包c(diǎn)ommons-pool2-2.3.jar访得、jedis-2.7.2.jar、tomcat8_redis_session-0.0.1-SNAPSHOT.jar拷貝到tomcat的lib下
新增tomcat context.xml配置
host="127.0.0.1"
port="6379"
database="0"
maxInactiveInterval="60" />
資料在項(xiàng)目的data目錄下
4. 測試
在web項(xiàng)目啟動tomcat并使用如下代碼進(jìn)行測試
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{HttpSessionsession=request.getSession();/*//1.設(shè)置Sessionfor(inti=0;i<10;i++){session.setAttribute("name"+i,"session_data_"+i);}*///2.注釋第一步,重啟tomcat后看是否還可以讀取到SessionStringstr="";for(inti=0;i<10;i++){str=str+session.getAttribute("name"+i)+"
";}response.setContentType("text/html");PrintWriterout=response.getWriter();out.println(str);out.flush();out.close();//訪問:http://localhost:8080/tomcat8_redis_session_web/servlet/TestRedisSessionServlet}
參考網(wǎng)址:
redis + Tomcat 8 的session共享解決 【http://www.cnblogs.com/interdrp/p/4868740.html 】
Tomcat7+Redis存儲Session【http://blog.csdn.net/caiwenfeng_for_23/article/details/45666831】
用Redis存儲Tomcat集群的Session【http://blog.csdn.net/chszs/article/details/42610365 】
分布式集群系統(tǒng)下的高可用session解決方案【http://tendyming.iteye.com/blog/1815136 】
《大型網(wǎng)站系統(tǒng)與Java中間件實(shí)踐》
《深入分析Java Web技術(shù)內(nèi)幕》
code:
https://github.com/JeromeSuz/tomcat8_redis_session
https://github.com/JeromeSuz/tomcat8_redis_session_web