來自 : http://www.cnblogs.com/zhangdie/p/5730194.html
單節點低負荷的情況下,我們通常把一個WEB應用打成WAR包放WEB應用伺服器,如TOMCAT下運作就行了(如圖1)。但随着使用者量的增加,系統負載日益增長,這時我們通常就會采用多台WEB應用伺服器組成叢集來分擔負荷(tomcat1, tomcat2上同時部署了應用application1; tomcat3上單獨部署了應用application3),這時某一使用者對同一應用的通路就有可能配置設定到從不同的TOMCAT通路這個應用(如圖2, session1和session2同時通路application1)。假設我們的WEB通路請求都是無狀态的,多個背景應用和一個背景應用的處理就沒什麼差別了,根據每次請求的參數進行相關邏輯處理就行。但通常我們會将使用者資訊,鑒權的資料等放入session中做使用者鑒權, 使用者狀态資料等基礎架構的處理,這時我們每次配置設定到WEB伺服器背景的通路請求就需要記錄session狀态及資料了,確定每次使用者通路,背景從session取出的資料是一緻的。
到這裡,我們已經可以清楚的看到,叢集環境下,某一使用者請求通路APPLICATION1,第一次請求被NGINX轉發到TOMCAT1,産生了SESSION1,這時,APPLICATION1存了某一資料進SESSION1。随後,該使用者進行第二次請求,這時,NGINX将該請求轉發到TOMCAT2,這時TOMCAT2産生了一個新的SESSION2來通路APPLICTION1,如果這時APPLICTION1從SESSION中取剛存入的資料,因為SESSION2是TOMCAT2新産生的,并不是剛才存入資料的SESSION1,就會取不到我們想要的資料.
是以,很自然的,我們就想到需要保持session1和session2的一緻性。
而保持session1和session2的一緻性有兩種很明顯的方法,一種是保持session1和session2中的資料一緻,二是讓session1和session2成為一個session,即如果同一使用者通路applcation1, tomcat1和tomcat2産生的是一個共享的session。下面就介紹下這兩種處理方式.
1. TOMCAT間的 session複制。
顧名思義,就是把一台TOMCAT上session發生變更的時候, 将變更的資料分發給其他TOMCAT。如圖3
tomcat間是以IP多點傳播發送變更的資料,将資料發送到叢集組的其他成員。這裡,同一使用者通路APPLICATION1的session資料互相有了同步,他們的資料是相同的,就用app1sesson表示。
配置方法是配置 conf/server.xml 檔案中的 Manager ,Channel,以及WEB.XML的distributable 屬性。 網上已有很多配置介紹,這裡就不啰嗦了。
2. 采用 memcached session manager 共享session。
這裡, tomcat1和tomcat2産生的session1和session2 在 session mananger 的管理下,都使用的是緩存中的共享session,通路應用時這樣傳到application1應用的session就是圖中的共享session.
這種共享session方案可采用google的memcached session manager, 注意下載下傳時對應TOMCAT版本。 它以memcached作為緩存,安裝時所有tomcat節點需要安裝memcached-session-manager。支援sticky session 和 non-sticky session。大概原理是當一個請求結束時,session會被送回Memcached進行備份。當下一次請求開始時,本地Session可用,直接服務,請求結束後,session又被送回Memcached備份。如果下一次請求會被路由到其他Tomcat上。負責處理此此請求的Tomcat并不清楚Session的資訊。此時它會從Memcached查找該Session,更新該Session并将其儲存在本機内容。此次請求結束,session被修改,送回Memcached備份。如下圖:
配置方法網上也有很多介紹,主要是修改 tomcat下 conf/server.xml, memcachedNodes可指定多個memcached節點, 逗号隔開。
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:localhost:11211"
requestUriIgnorePattern=".*\.(png|gif|jpg|css|js){1}quot;"
sessionBackupAsync="false"
sessionBackupTimeout="1800000"
copyCollectionsForSerialization="false"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
如是非粘性,配置 sticky="false":
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:localhost:11211"
sticky="false"
requestUriIgnorePattern=".*\.(png|gif|jpg|css|js){1}quot;"
sessionBackupAsync="false"
lockingMode="uriPattern:/path1|/path2"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
來自 : http://blog.csdn.net/qh_java/article/details/45955923
前兩種均需要使用 memcached 或redis 存儲 session ,最後一種使用 terracotta 伺服器共享。
建議使用 redis,不僅僅因為它可以将緩存的内容持久化,還因為它支援的單個對象比較大,而且資料類型豐富,
不隻是緩存 session,還可以做其他用途,一舉幾得啊。
1、使用 filter 方法存儲
這種方法比較推薦,因為它的伺服器使用範圍比較多,不僅限于tomcat ,而且實作的原理比較簡單容易控制。
可以使用memcached-session-filter
官方網址:http://code.google.com/p/memcached-session-filter/
官方介紹:解決叢集環境下javaweb容器session共享,使用filter攔截器和memcached實作。在tomcat 6和websphere8測試通過,現網并發2000,日PV量1100萬。
暫不支援sessionevent包括create destory 和 attribute change
東西很不錯,體積很小,不過這個東東要和spring 一起使用,而且要求存儲到 memcached 的對象要實作 java 的序列化接口
大家也知道,java本身的序列化性能也很一般。
我将其簡單擴充了一下,不再依賴spring ,并且利用 javolution 實作序列化,緩存的對象不再有限制。
暫時沒有發現 redis的實作,後面将自己實作使用 redis 存儲并且序列化使用 kyro ,詳細情況有時間再單獨寫出來。
2、使用 tomcat sessionmanager 方法存儲
這種方法伺服器隻能使用 tomcat,但網上有針對 memcached 和 redis 實作,直接配置就行了。
memcached 實作:
網址:http://code.google.com/p/memcached-session-manager/
修改 tomcat 的 conf 目錄下的context.xml 檔案:
<ManagerclassName="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:localhost:11211n2:localhost:11212"
failoverNodes="n2"
requestUriIgnorePattern=".*\.(png|gif|jpg|css|js)$"
sessionBackupAsync="false"
sessionBackupTimeout="100"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
copyCollectionsForSerialization="false" />
以上是以 1.3 版為例子,需要用的jar 包:
memcached-session-manager-1.3.0.jar
msm-javolution-serializer-1.3.0.jar
javolution-5.4.3.1.jar
memcached-2.4.2.jar
redis 實作:
網址:https://github.com/jcoleman/tomcat-redis-session-manager
同樣修改 tomcat 的 conf目錄下的 context.xml 檔案:
<ValveclassName="com.radiadesign.catalina.session.RedisSessionHandlerValve"/>
<ManagerclassName="com.radiadesign.catalina.session.RedisSessionManager"
host="localhost"
port="6379"
database="0"
maxInactiveInterval="60"/>
以上是以 1.2 版為例子,需要用的jar 包:
tomcat-redis-session-manager-1.2-tomcat-6.jar
jedis-2.1.0.jar
commons-pool-1.6.jar
3、使用 terracotta 伺服器共享
這種方式配置有點複雜,大家到網上搜尋一下吧。
以上配置成功後,前端使用 nginx進行負載均衡就行了,同時使用 Gzip 壓縮 和 靜态檔案緩存。
以下是執行個體:
一、nginx+tomcat+memcached (依賴架包下載下傳)
1.memcached配置:(v1.4.13)
節點1(192.168.159.131:11444)
節點2(192.168.159.131:11333)
2.tomcat配置
tomcat1(192.168.159.128:8081)
tomcat2(192.168.159.128:8082)
3.nginx安裝在192.168.159.131。
首先,是配置tomcat,使其将session儲存到memcached上。有兩種方法:
方法一:在server.xml中配置。
找到host節點,加入
<ContextdocBase="/var/www/html" path="">
<ManagerclassName="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:192.168.159.131:11444n2:192.168.159.131:11333"
requestUriIgnorePattern=".*\.(png|gif|jpg|css|js)$"
sessionBackupAsync="false"sessionBackupTimeout="3000"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
copyCollectionsForSerialization="false"/>
</Context>
方法二:在context.xml中配置。
找到Context節點,在context中加入
<ManagerclassName="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:192.168.159.131:11444"
requestUriIgnorePattern=".*\.(png|gif|jpg|css|js)$"
sessionBackupAsync="false"sessionBackupTimeout="3000"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
copyCollectionsForSerialization="false" />
其次,配置nginx,用于測試session保持共享。
upstream xxy.com {
server 192.168.159.128:8081 ;
server 192.168.159.128:8082 ;
}
log_format www_xy_com '$remote_addr - $remote_user [$time_local] $request '
'"$status"$body_bytes_sent "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for"';
server
{
listen 80;
server_name xxy.com;
location/ {
proxy_pass http://xxy.com;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
access_log /data/base_files/logs/www.xy.log www_xy_com;
}
最後,将你的應用放到兩個tomcat中,并依次啟動memcached、tomcat、nginx。通路你的nginx,可以發現兩個tomcat中的session可以保持共享了。
二、nginx+tomcat+redis (依賴架包下載下傳)
1.redis配置(192.168.159.131:16300)(v2.8.3)
2.tomcat配置
tomcat1(192.168.159.130:8081)
tomcat2(192.168.159.130:8082)
3.nginx安裝在192.168.159.131。
首先,是配置tomcat,使其将session儲存到redis上。有兩種方法,也是在server.xml或context.xml中配置,不同的是memcached隻需要添加一個manager标簽,而redis需要增加的内容如下:(注意:valve标簽一定要在manager前面。)
配置和memcached 一樣 找到Context節點,在context中加入
<ValveclassName="com.radiadesign.catalina.session.RedisSessionHandlerValve"/>
<ManagerclassName="com.radiadesign.catalina.session.RedisSessionManager"
host="192.168.159.131"
port="16300"
database="0"
maxInactiveInterval="60"/>
其次,配置nginx,用于測試session保持共享。
upstream redis.xxy.com {
server 192.168.159.130:8081;
server 192.168.159.130:8082;
}
log_format www_xy_com '$remote_addr - $remote_user [$time_local] $request '
'"$status"$body_bytes_sent "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for"';
server
{
listen 80;
server_name redis.xxy.com;
location/ {
proxy_pass http://redis.xxy.com;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
access_log /data/base_files/logs/redis.xxy.log www_xy_com;
}
最後,将你的應用放到兩個tomcat中,并依次啟動redis、tomcat、nginx。通路你的nginx,可以發現兩個tomcat中的session可以保持共享了。