對於web應用集羣的技術實現而言,最大的難點就是:如何能在集羣中的多個節點之間保持數據的一致性,會話(Session)信息是這些數據中最重要的一塊。要實現這一點, 大致上有兩種方式: 一種是把全部Session數據放到一臺服務器上或者數據庫中,集羣中的全部節點經過訪問這臺Session服務器來獲取數據; 另外一種就是在集羣中的全部節點間進行Session數據的同步拷貝,任何一個節點均保存了全部的Session數據。javascript
Tomcat集羣session同步方案有如下幾種方式: 1)使用tomcat自帶的cluster方式,多個tomcat間自動實時複製session信息,配置起來很簡單。但這個方案的效率比較低,在大併發下表現並很差。 2)利用nginx的基於訪問ip的hash路由策略,保證訪問的ip始終被路由到同一個tomcat上,這個配置更簡單。但若是應用是某一個局域網大量用戶同時登陸,這樣負載均衡就沒什麼做用了。 3)利用nginx插件實現tomcat集羣和session同步,nginx-upstream-jvm-route-0.1.tar.gz,是一個Nginx的擴展模塊,用來實現基於Cookie的Session Sticky的功能。 4)利用memcached實現(MSM工具)。memcached存儲session,並把多個tomcat的session集中管理,前端在利用nginx負載均衡和動靜態資源分離,在兼顧系統水平擴展的同時又能保證較高的性能。 5)利用redis實現。使用redis不只僅能夠將緩存的session持久化,還由於它支持的單個對象比較大,並且數據類型豐富,不僅是緩存 session,還能夠作其餘用途,能夠一舉幾得。 6)利用filter方法實現。這種方法比較推薦,由於它的服務器使用範圍比較多,不只限於tomcat ,並且實現的原理比較簡單容易控制。 7)利用terracotta服務器共享session。這種方式配置比較複雜。php
在Tomcat集羣中,當一個節點出現故障,雖然有高可用集羣來負責故障轉移,但用戶的session信息如何保持呢? 下面介紹第4種方案,session複製同步使用MSM(Memcache-Session-Manager),即利用MSM+Memcached作Session共享。css
MSM介紹:(詳細介紹能夠參考:http://www.cnblogs.com/kevingrace/p/6401025.html) MSM是一個高可用的Tomcat Session共享解決方案,除了能夠從本機內存快速讀取Session信息(僅針對黏性Session)外,還可以使用Memcached存取Session,以實現高可用。 傳統tomcat集羣,會話複製隨着結點數增多,擴展性成爲瓶頸。MSM使用memcached完成統一管理tomcat會話,避免tomcat結點間過多會話複製。 MSM利用Value(Tomcat 閥)對Request進行跟蹤。Request請求到來時,從memcached加載session,Request請求結束時,將tomcat session更新至memcached,以達到session共享之目的, 支持sticky和non-sticky模式: sticky : 會話粘連模式(黏性session)。客戶端在一臺tomcat實例上完成登陸後,之後的請求均會根據IP直接綁定到該tomcat實例。 no-sticky:會話非粘連模式(非粘性session)。客戶端的請求是隨機分發,多臺tomcat實例均會收到請求。html
在進行環境部署以前,要對cookie和session的工做機制很是瞭解,若是不瞭解其中的原理且只是機械性地去按照參考文檔部署,那麼這是毫無心義的。 a)cookie是怎麼工做的? 加入咱們建立了一個名字爲login的Cookie來包含訪問者的信息,建立Cookie時,服務器端的Header以下面所示,這裏假設訪問者的註冊名是「wangshibo」,同時還對所建立的Cookie的屬性如path、domain、expires等進行了指定。前端
1
2
|
Set-Cookie:login=wangshibo;path=/;domain=msn.com;
expires=Monday,01-Mar-99 00:00:01 GMT
|
上面這個Header會自動在瀏覽器端計算機的Cookie文件中添加一條記錄。瀏覽器將變量名爲「login」的Cookie賦值爲「wangshibo」。 注意,在實際傳遞過程當中這個Cookie的值是通過了URLEncode方法的URL編碼操做的。 這個含有Cookie值的HTTP Header被保存到瀏覽器的Cookie文件後,Header就通知瀏覽器將Cookie經過請求以忽略路徑的方式返回到服務器,完成瀏覽器的認證操做。 此外,咱們使用了Cookie的一些屬性來限定該Cookie的使用。例如Domain屬性可以在瀏覽器端對Cookie發送進行限定,具體到上面的例子,該Cookie只能傳到指定的服務器上,而決不會跑到其餘的Web站點上去。Expires屬性則指定了該Cookie保存的時間期限,例如上面的Cookie在瀏覽器上只保存到1999年3月1日1秒。 固然,若是瀏覽器上Cookie太多,超過了系統所容許的範圍,瀏覽器將自動對它進行刪除。至於屬性Path,用來指定Cookie將被髮送到服務器的哪個目錄路徑下。 說明:瀏覽器建立了一個Cookie後,對於每個針對該網站的請求,都會在Header中帶着這個Cookie;不過,對於其餘網站的請求Cookie是絕對不會跟着發送的。並且瀏覽器會這樣一直髮送,直到Cookie過時爲止。java
b)session是如何工做的? 因爲http是無狀態的協議,你訪問了頁面A,而後再訪問B頁面,http沒法肯定這2個訪問來自一我的,所以要用cookie或session來跟蹤用戶,根據受權和用戶身份來 顯示不一樣的頁面。好比用戶A登錄了,那麼能看到本身的我的信息,而B沒登錄,沒法看到我的信息。還有A可能在購物,把商品放入購物車,此時B也有這個過程, 你沒法肯定A,B的身份和購物信息,因此須要一個session ID來維持這個過程。 cookie是服務器發給客戶端並保持在客戶端的一個文件,裏面包含了用戶的訪問信息(帳戶密碼等),能夠手動刪除或設置有效期,在下次訪問的時候,會返給服務器。 注意:cookie能夠被禁用,因此要想其餘辦法,這就是session。cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。cookie同時也是session id的載體,cookie保存session id。另外:cookie不是很安全,別人能夠分析存放在本地的cookie並進行cookie欺騙,考慮到安全應當使用session。session是服務器端緩存,cookie是客戶端緩存。因此建議:將登錄信息等重要信息存放爲session;其餘信息若是須要保留,能夠放在cookie中, 好比:你去商場購物,商場會給你辦一張會員卡,下次你來出示該卡,會有打折優惠,該卡能夠本身保存(cookie),或是商場代爲保管,因爲會員太多,我的須要保存卡號信息(session ID)。 node
爲何要持久化session(共享session)? 由於:在客戶端每一個用戶的Session對象存在Servlet容器中,若是Tomcat服務器重啓或者宕機的話,那麼該session就會丟失,而客戶端的操做會因爲session丟失而形成數據丟失;若是當前用戶訪問量巨大,每一個用戶的Session裏存放大量數據的話,那麼就很佔用服務器大量的內存,進而導致服務器性能受到影響。 可使用數據庫持久化session,分爲物理數據庫和內存數據庫。物理數據庫備份session,因爲其性能緣由,不推薦;內存數據庫可使用redis和memcached,這裏介紹memcached的方法。linux
MSM工做原理: a)Sticky Session(黏性) 模式下的工做原理: Tomcat本地Session爲主Session,Memcached 中的Session爲備Session。 安裝在Tomcat上的MSM使用本機內存保存Session,當一個請求執行完畢以後,若是對應的Session在本地不存在(即某用戶的第一次請求),則將該Session複製一份至Memcached;當該Session的下一個請求到達時,會使用Tomcat的本地Session,請求處理結束以後,Session的變化會同步更新到 Memcached,保證數據一致。 當集羣中的一個Tomcat掛掉,下一次請求會被路由到其餘Tomcat上。負責處理此此請求的Tomcat並不清楚Session信息,因而從Memcached查找該Session,更新該Session並將其保存至本機。這次請求結束,Session被修改,送回Memcached備份。 b)Non-sticky Session (非黏性)模式下的工做原理(記住:多臺tomcat集羣或多個tomcat實例時須要選擇Non-Sticky模式,即sticky="false"): Tomcat本地Session爲中轉Session,Memcached爲主備Session。 收到請求,加載備Session至本地容器,若備Session加載失敗則從主Session加載; 請求處理結束以後,Session的變化會同步更新到Memcached,並清除Tomcat本地Session。nginx
------------------------------------------------------------------------------------------------------------ 廢話很少說了,下面直接看nginx+memcached+tomcat實現session共享的集羣操做記錄:: 1、集羣實驗環境信息c++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
主機 端口 開源軟件
192.168.1.118 80 nginx(nginx-1.8.1)
192.168.1.118 8081 tomcat1(版本爲tomcat7)
192.168.1.118 8091 tomcat2
192.168.1.118 11211 memcached(memcached-1.4.34)
192.168.1.118 11212 memcached(memcached-1.4.34)
服務器系統均是centos6.8
我這裏是在一臺測試服務器(192.168.1.118
/110
.110.115.118)上操做的,即nginx、memcached、tomcat均是部署在同一臺服務器上,只是爲了測試。
若是在生產環境下,ngixn、tocmat、memcached應該是部署到不一樣的服務器上。
爲何在兩個tomcat實例前要放一個nginx?
1)nginx能夠做爲兩個tomcat的負載均衡,均衡兩個tomat負載壓力,負載均衡也可使得客戶端訪問可使用統一的url,若是沒有nginx,那麼訪問tomcat1必需要用http:
//localhost
:8081/,而訪問tomcat2須要用http:
//localhost
:8091/
2)nginx處理靜態資源的性能比tomcat好不少
|
實驗拓撲圖:
2、nginx安裝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
1)安裝依賴包
[root@linux-node3 ~]
# yum -y install gcc gcc-c++
2)安裝pcre庫
[root@linux-node3 ~]
# cd /usr/local/src/
[root@linux-node3 src]
# wget https://jaist.dl.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz
[root@linux-node3 src]
# tar -zvxf pcre-8.37.tar.gz
[root@linux-node3 src]
# cd pcre-8.37
[root@linux-node3 pcre-8.37]
# ./configure && make && make install
3)安裝zlib庫
[root@linux-node3 src]
# wget http://www.zlib.net/zlib-1.2.11.tar.gz
[root@linux-node3 src]
# tar -zvxf zlib-1.2.11.tar.gz
[root@linux-node3 zlib-1.2.11]
# ./configure && make && make install
4)安裝openssl
[root@linux-node3 src]
# wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
[root@linux-node3 src]
# tar -zvxf openssl-1.0.1c.tar.gz && cd openssl-1.0.1c && ./config && make && make install
5)安裝nginx
特別注意要指定prce zlib openssl原碼包位置
[root@linux-node3 src]
# wget http://nginx.org/download/nginx-1.8.1.tar.gz
[root@linux-node3 src]
# tar -zvxf nginx-1.8.1.tar.gz
[root@linux-node3 src]
# cd nginx-1.8.1
[root@linux-node3 nginx-1.8.1]
# ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-pcre=/usr/local/src/pcre-8.37 --with-zlib=/usr/local/src/zlib-1.2.11 --with-openssl=/usr/local/src/openssl-1.0.1c
[root@linux-node3 nginx-1.8.1]
# make && make install
6)安裝成功後配置nginx
[root@linux-node3 nginx-1.8.1]
# vim /usr/local/nginx/conf/nginx.conf
#user nobody;
worker_processes 8;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
worker_rlimit_nofile 65535;
events {
use epoll;
worker_connections 65535;
}
http {
include mime.types;
default_type application
/octet-stream
;
charset utf-8;
######
## set access log format
######
log_format main
'$http_x_forwarded_for $remote_addr $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_cookie" $host $request_time'
;
#######
## http setting
#######
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
fastcgi_connect_timeout 30000;
fastcgi_send_timeout 30000;
fastcgi_read_timeout 30000;
fastcgi_buffer_size 256k;
fastcgi_buffers 8 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
##cache##
client_header_timeout 60s;
client_body_timeout 60s;
client_max_body_size 10m;
client_body_buffer_size 1m;
proxy_connect_timeout 5;
proxy_read_timeout 60;
proxy_send_timeout 5;
proxy_buffer_size 64k;
proxy_buffers 4 128k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 1m;
proxy_temp_path
/home/temp_dir
;
proxy_cache_path
/home/cache
levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;
##end##
gzip
on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 9;
gzip_types text
/plain
application
/x-javascript
text
/css
application
/xml
text
/javascript
application
/x-httpd-php
;
gzip_vary on;
## includes vhosts
include vhosts/*.conf;
}
[root@linux-node3 nginx-1.8.1]
# cd /usr/local/nginx/conf/
[root@linux-node3 conf]
# mkdir vhosts
[root@linux-node3 conf]
# cd vhosts/
[root@linux-node3 vhosts]
# vim test.conf
upstream tomcat-lb {
server 127.0.0.1:8081;
server 127.0.0.1:8091;
}
server {
listen 80;
server_name www.wangshibo.com;
location / {
proxy_pass http:
//tomcat-lb
;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ .*\.(gif|jpg|png|htm|html|css|ico|flv|swf)(.*) {
proxy_pass http:
//tomcat-lb
;
proxy_redirect off;
proxy_set_header Host $host;
proxy_cache cache_one;
proxy_cache_valid 200 302 1h;
proxy_cache_valid 301 1d;
proxy_cache_valid any 10m;
expires 30d;
proxy_cache_key $host$uri$is_args$args;
}
}
|
3、memcached安裝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
[root@linux-node3 src]
# yum -y install libevent libevent-devel
[root@linux-node3 src]
# wget http://memcached.org/files/memcached-1.4.34.tar.gz
[root@linux-node3 src]
# tar -zvxf memcached-1.4.34.tar.gz
[root@linux-node3 src]
# cd memcached-1.4.34
[root@linux-node3 memcached-1.4.34]
# ./configure --prefix=/usr/local/memcached
[root@linux-node3 memcached-1.4.34]
# make && make install
啓動memcached,端口11211能夠根據本身須要修改不一樣端口
[root@linux-node3 memcached-1.4.34]
# /usr/local/memcached/bin/memcached -d -m 512 -u root -p 11211 -c 1024 -P /var/lib/memcached.11211pid
[root@linux-node3 memcached-1.4.34]
# /usr/local/memcached/bin/memcached -d -m 512 -u root -p 11212 -c 1024 -P /var/lib/memcached.11212pid
[root@linux-node3 memcached-1.4.34]
# ps -ef|grep memcached
root 44007 1 0 14:21 ? 00:00:00
/usr/local/memcached/bin/memcached
-d -m 512 -u root -p 11211 -c 1024 -P
/var/lib/memcached
.11211pid
root 44018 1 0 14:21 ? 00:00:00
/usr/local/memcached/bin/memcached
-d -m 512 -u root -p 11212 -c 1024 -P
/var/lib/memcached
.11212pid
root 44038 21647 0 14:22 pts
/2
00:00:00
grep
memcached
測試一下memcached鏈接,以下說明成功(輸入quit退出)
[root@linux-node3 ~]
# telnet 192.168.1.118 11211
Trying 192.168.1.118...
Connected to 192.168.1.118.
Escape character is
'^]'
.
[root@linux-node3 ~]
# telnet 192.168.1.118 11212
Trying 192.168.1.118...
Connected to 192.168.1.118.
Escape character is
'^]'
.
|
4、安裝jdk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
查看CentOS自帶JDK是否已安裝
[root@linux-node3 ~]
# yum list installed |grep java
[root@linux-node3 ~]
#
如有自帶安裝的JDK,如何卸載CentOS系統自帶Java環境?
卸載JDK相關文件輸入:yum -y remove java-1.7.0-openjdk*。
卸載tzdata-java輸入:yum -y remove tzdata-java.noarch。
當結果顯示爲Complete!即卸載完畢。
注:
"*"
表示卸載掉java 1.7.0的全部openjdk相關文件。
查看yum庫中的java安裝包
[root@linux-node3 ~]
# yum -y list java*
........
java-1.5.0-gcj.x86_64 1.5.0.0-29.1.el6 base
java-1.5.0-gcj-devel.x86_64 1.5.0.0-29.1.el6 base
java-1.5.0-gcj-javadoc.x86_64 1.5.0.0-29.1.el6 base
java-1.5.0-gcj-src.x86_64 1.5.0.0-29.1.el6 base
java-1.6.0-openjdk.x86_64 1:1.6.0.41-1.13.13.1.el6_8 updates
java-1.6.0-openjdk-demo.x86_64 1:1.6.0.41-1.13.13.1.el6_8 updates
java-1.6.0-openjdk-devel.x86_64 1:1.6.0.41-1.13.13.1.el6_8 updates
java-1.6.0-openjdk-javadoc.x86_64 1:1.6.0.41-1.13.13.1.el6_8 updates
java-1.6.0-openjdk-src.x86_64 1:1.6.0.41-1.13.13.1.el6_8 updates
java-1.7.0-openjdk.x86_64 1:1.7.0.131-2.6.9.0.el6_8 updates
java-1.7.0-openjdk-demo.x86_64 1:1.7.0.131-2.6.9.0.el6_8 updates
java-1.7.0-openjdk-devel.x86_64 1:1.7.0.131-2.6.9.0.el6_8 updates
java-1.7.0-openjdk-javadoc.noarch 1:1.7.0.131-2.6.9.0.el6_8 updates
java-1.7.0-openjdk-src.x86_64 1:1.7.0.131-2.6.9.0.el6_8 updates
java-1.8.0-openjdk.x86_64 1:1.8.0.121-0.b13.el6_8 updates
java-1.8.0-openjdk-debug.x86_64 1:1.8.0.121-0.b13.el6_8 updates
java-1.8.0-openjdk-demo.x86_64 1:1.8.0.121-0.b13.el6_8 updates
java-1.8.0-openjdk-demo-debug.x86_64 1:1.8.0.121-0.b13.el6_8 updates
java-1.8.0-openjdk-devel.x86_64 1:1.8.0.121-0.b13.el6_8 updates
java-1.8.0-openjdk-devel-debug.x86_64 1:1.8.0.121-0.b13.el6_8 updates
java-1.8.0-openjdk-headless.x86_64 1:1.8.0.121-0.b13.el6_8 updates
java-1.8.0-openjdk-headless-debug.x86_64 1:1.8.0.121-0.b13.el6_8 updates
java-1.8.0-openjdk-javadoc.noarch 1:1.8.0.121-0.b13.el6_8 updates
java-1.8.0-openjdk-javadoc-debug.noarch 1:1.8.0.121-0.b13.el6_8 updates
java-1.8.0-openjdk-src.x86_64 1:1.8.0.121-0.b13.el6_8 updates
java-1.8.0-openjdk-src-debug.x86_64 1:1.8.0.121-0.b13.el6_8 updates
........
以yum庫中java-1.7.0爲例
注:
"*"
表示將java-1.7.0的全部相關Java程序都安裝上。
[root@linux-node3 ~]
# yum -y install java-1.7.0-openjdk*
查看剛安裝的Java版本信息。
輸入:java -version 可查看Java版本;
輸入:javac 可查看Java的編譯器命令用法
[root@linux-node3 ~]
# java -version
java version
"1.7.0_131"
OpenJDK Runtime Environment (rhel-2.6.9.0.el6_8-x86_64 u131-b00)
OpenJDK 64-Bit Server VM (build 24.131-b00, mixed mode)
[root@linux-node3 ~]
# which java
/usr/bin/java
[root@linux-node3 ~]
# ll /usr/bin/java
lrwxrwxrwx. 1 root root 22 Feb 14 22:25
/usr/bin/java
->
/etc/alternatives/java
[root@linux-node3 ~]
# ll /etc/alternatives/java
lrwxrwxrwx. 1 root root 46 Feb 14 22:25
/etc/alternatives/java
->
/usr/lib/jvm/jre-1
.7.0-openjdk.x86_64
/bin/java
[root@linux-node3 ~]
# cd /usr/lib/jvm
[root@linux-node3 jvm]
# ll
total 4
lrwxrwxrwx. 1 root root 26 Feb 14 22:25 java ->
/etc/alternatives/java_sdk
lrwxrwxrwx. 1 root root 32 Feb 14 22:25 java-1.7.0 ->
/etc/alternatives/java_sdk_1
.7.0
drwxr-xr-x. 9 root root 4096 Feb 14 22:25 java-1.7.0-openjdk-1.7.0.131.x86_64
lrwxrwxrwx. 1 root root 35 Feb 14 22:25 java-1.7.0-openjdk.x86_64 -> java-1.7.0-openjdk-1.7.0.131.x86_64
lrwxrwxrwx. 1 root root 34 Feb 14 22:25 java-openjdk ->
/etc/alternatives/java_sdk_openjdk
lrwxrwxrwx. 1 root root 21 Feb 14 22:25 jre ->
/etc/alternatives/jre
lrwxrwxrwx. 1 root root 27 Feb 14 22:25 jre-1.7.0 ->
/etc/alternatives/jre_1
.7.0
lrwxrwxrwx. 1 root root 39 Feb 14 22:25 jre-1.7.0-openjdk.x86_64 -> java-1.7.0-openjdk-1.7.0.131.x86_64
/jre
lrwxrwxrwx. 1 root root 29 Feb 14 22:25 jre-openjdk ->
/etc/alternatives/jre_openjdk
由上可知,java的home目錄是
/usr/lib/jvm/java-1
.7.0-openjdk.x86_64
設置java的環境變量
[root@115 ~]
# vim /etc/profile
.......
export
JAVA_HOME=
/usr/lib/jvm/java-1
.7.0-openjdk.x86_64
export
CLASSPATH=.:$JAVA_HOME
/jre/lib/rt
.jar:$JAVA_HOME
/lib/dt
.jar:$JAVA_HOME
/lib/tools
.jar
export
PATH=$PATH:$JAVA_HOME
/bin
[root@linux-node3 jvm]
# source /etc/profile
|
5、安裝與配置tomcat 1)安裝tomcat [root@linux-node3 src]# wget http://apache.fayea.com/tomcat/tomcat-7/v7.0.75/bin/apache-tomcat-7.0.75.tar.gz [root@linux-node3 src]# tar -zvxf apache-tomcat-7.0.75.tar.gz [root@linux-node3 src]# mv apache-tomcat-7.0.75 /usr/local/tomcat1
2)添加memcached和msm(Memcached_Session_Manager)的依賴jar包,以下:
1
2
3
4
5
6
7
8
9
|
asm-3.2.jar
kryo-1.03.jar
kryo-serializers-0.10.jar
memcached-session-manager-1.7.0.jar
memcached-session-manager-tc7-1.7.0.jar
minlog-1.2.jar
msm-kryo-serializer-1.6.3.jar
reflectasm-0.9.jar
spymemcached-2.7.3.jar
|
注意:memcached-session-manager-tc7-1.7.0.jar中的tc7爲tomcat的版本號。必定要注意:不一樣版本號的tomcat,對應的msm包也不一樣。此處爲tomcat7的jar包
上面依賴包下載地址:https://pan.baidu.com/s/1eRRncpO 提取密碼:y56i
--------------------------------------------------------------------------------------------------------------------------------- msm相關版本的jar包下載地址:http://repo1.maven.org/maven2/de/javakaffee/msm/ spymemcached相關版本下載地址:http://repo1.maven.org/maven2/net/spy/spymemcached ---------------------------------------------------------------------------------------------------------------------------------
把依賴包下載後所有上傳到tomcat1和tomcat2的安裝路徑下的lib/ 目錄下
3)配置tomcat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
這裏個人tomcat1的服務端口用的是8081,因此須要將tomcat1的server.xml中默認的8080改爲8081
[root@linux-node3 ~]
# cd /usr/local/tomcat1/conf/
[root@linux-node3 conf]
# cp server.xml server.xml.bak
[root@linux-node3 conf]
# vim server.xml
.......
<Connector port=
"8081"
protocol=
"HTTP/1.1"
connectionTimeout=
"20000"
redirectPort=
"8443"
/>
......
<Engine name=
"Catalina"
defaultHost=
"localhost"
jvmRoute=
"tomcat1"
>
......
注意:啓有Engine標籤中的jvmRoute屬性,啓用的目的就是爲了區分session是在哪一個節點上生成的
這個Engine name是非必選 ,只有選擇了sticky模式才加入jvmRoute屬性。這裏爲了實驗效果,咱們暫且選擇這個設置項。
不一樣的tomcat實例jvmRoute取值不能相同。
例:8081端口的tomcat實例jvmRoute=tomcat1,8091端口的tomcat實例jvmRoute=tomcat2
|
接下來進行序列化tomcat配置,修改conf/context.xml文件。 序列化tomcat配置的方法有不少種:java默認序列化tomcat配置、javolution序列化tomcat配置、xstream序列化tomcat配置、flexjson序列化tomcat配置和kryo序列化tomcat配置。官網介紹說 使用kryo 序列化tomcat的效率最高,因此這裏只介紹kryo序列化。 在No-Stick模式和Stick模式下context.xml文件配置也有所不一樣(通常用的是No-Stick模式) a)No-Stick模式(記住:多臺tomcat集羣或多個tomcat實例時 須要選擇Non-Sticky模式,即sticky="false")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[root@linux-node3 ~]
# cd /usr/local/tomcat1/conf/
[root@linux-node3 conf]
# cp context.xml context.xml.bak
[root@linux-node3 conf]
# vim context.xml //在<Context>和</Context>之間添加下面內容
<Manager className=
"de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes=
"n1:192.168.1.118:11211 n2:192.168.1.118:11212"
lockingMode=
"auto"
sticky=
"false"
requestUriIgnorePattern=
".*\.(png|gif|jpg|css|js)$"
sessionBackupAsync=
"true"
sessionBackupTimeout=
"1800000"
copyCollectionsForSerialization=
"true"
transcoderFactoryClass=
"de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
而後將congtext.xml文件拷貝到tomcat2的相同路徑下
|
b)Stick模式。故障轉移配置節點(failoverNodes),不能使用在non-sticky sessions模式,多個使用空格或逗號分開,配置某個節點爲備份節點,當其餘節點都不可用時纔會存儲到備份節點,適用於sticky模式(即一臺tomcat,多臺memcached)。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[root@linux-node3 ~]
# cd /usr/local/tomcat1/conf/
[root@linux-node3 conf]
# cp context.xml context.xml.bak
[root@linux-node3 conf]
# vim context.xml //在<Context>和</Context>之間添加下面內容
<Manager className=
"de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes=
"n1:192.168.1.118:11211 n2:192.168.1.118:11212"
sticky=
"true"
failoverNodes=
"n2"
requestUriIgnorePattern=
".*\.(png|gif|jpg|css|js|swf|flv)$"
transcoderFactoryClass=
"de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
copyCollectionsForSerialization=
"true"
/>
而後將congtext.xml文件拷貝到tomcat2的相同路徑下,並將failoverNodes後面的參數改成n1
|
-------------------------------------------------------------------------------------------------------------- 注意:這裏實驗環境是開啓了兩個memcached端口,若是開啓一個memcached端口也能夠的,好比只開啓11211端口,則No-Stick模式的配置以下:
1
2
3
4
5
6
7
8
9
|
<Manager className=
"de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes=
"n1:192.168.1.118:11211"
sticky=
"false"
requestUriIgnorePattern=
".*\.(png|gif|jpg|css|js)$"
sessionBackupAsync=
"true"
sessionBackupTimeout=
"1800000"
copyCollectionsForSerialization=
"false"
transcoderFactoryClass=
"de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
|
--------------------------------------------------------------------------------------------------------------
6、配置tomcat集羣
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[root@linux-node3 ~]
# cd /usr/local/
[root@linux-node3
local
]
# cp -r tomcat1 tomcat2
修改server.xml文件裏的相應端口,防止tomcat1和tomcat2端口衝突
[root@linux-node3
local
]
# vim tomcat2/conf/server.xml
.......
<Server port=
"8006"
shutdown
=
"SHUTDOWN"
>
//
把8005修改爲8006
......
<Connector port=
"8091"
protocol=
"HTTP/1.1"
//
把8081修改爲8091根據本身來配置,修改後的8090與nginx配置同樣
connectionTimeout=
"20000"
redirectPort=
"8443"
/>
.....
<Connector port=
"8010"
protocol=
"AJP/1.3"
redirectPort=
"8443"
/>
//
把8009修改爲8010
.....
<Engine name=
"Catalina"
defaultHost=
"localhost"
jvmRoute=
"tomcat2"
>
//
把tomcat1改成tomcat2
|
7、啓動tomcat集羣
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
[root@linux-node3 ~]
# /usr/local/tomcat1/bin/startup.sh
Using CATALINA_BASE:
/usr/local/tomcat1
Using CATALINA_HOME:
/usr/local/tomcat1
Using CATALINA_TMPDIR:
/usr/local/tomcat1/temp
Using JRE_HOME:
/usr/lib/jvm/java-1
.7.0-openjdk.x86_64
Using CLASSPATH:
/usr/local/tomcat1/bin/bootstrap
.jar:
/usr/local/tomcat1/bin/tomcat-juli
.jar
Tomcat started.
[root@linux-node3 ~]
# /usr/local/tomcat2/bin/startup.sh
Using CATALINA_BASE:
/usr/local/tomcat2
Using CATALINA_HOME:
/usr/local/tomcat2
Using CATALINA_TMPDIR:
/usr/local/tomcat2/temp
Using JRE_HOME:
/usr/lib/jvm/java-1
.7.0-openjdk.x86_64
Using CLASSPATH:
/usr/local/tomcat2/bin/bootstrap
.jar:
/usr/local/tomcat2/bin/tomcat-juli
.jar
Tomcat started.
[root@linux-node3 ~]
# ps -ef|grep tomcat
root 29224 1 49 02:21 pts
/2
00:00:04
/usr/lib/jvm/java-1
.7.0-openjdk.x86_64
/bin/java
-Djava.util.logging.config.
file
=
/usr/local/tomcat1/conf/logging
.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -classpath
/usr/local/tomcat1/bin/bootstrap
.jar:
/usr/local/tomcat1/bin/tomcat-juli
.jar -Dcatalina.base=
/usr/local/tomcat1
-Dcatalina.home=
/usr/local/tomcat1
-Djava.io.tmpdir=
/usr/local/tomcat1/temp
org.apache.catalina.startup.Bootstrap start
root 29250 1 87 02:21 pts
/2
00:00:04
/usr/lib/jvm/java-1
.7.0-openjdk.x86_64
/bin/java
-Djava.util.logging.config.
file
=
/usr/local/tomcat2/conf/logging
.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -classpath
/usr/local/tomcat2/bin/bootstrap
.jar:
/usr/local/tomcat2/bin/tomcat-juli
.jar -Dcatalina.base=
/usr/local/tomcat2
-Dcatalina.home=
/usr/local/tomcat2
-Djava.io.tmpdir=
/usr/local/tomcat2/temp
org.apache.catalina.startup.Bootstrap start
root 29278 29157 0 02:21 pts
/2
00:00:00
grep
tomcat
[root@linux-node3 ~]
# lsof -i:8080
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 29224 root 55u IPv6 383017 0t0 TCP *:webcache (LISTEN)
[root@linux-node3 ~]
# lsof -i:8090
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
java 29250 root 55u IPv6 383056 0t0 TCP *:8090 (LISTEN)
|
8、啓動nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
[root@linux-node3 ~]
# /usr/local/nginx/sbin/nginx
[root@linux-node3 ~]
# ps -ef|grep nginx
root 29282 1 0 02:23 ? 00:00:00 nginx: master process
/usr/local/nginx/sbin/nginx
nobody 29283 29282 2 02:23 ? 00:00:00 nginx: worker process
nobody 29284 29282 1 02:23 ? 00:00:00 nginx: worker process
nobody 29285 29282 2 02:23 ? 00:00:00 nginx: worker process
nobody 29286 29282 2 02:23 ? 00:00:00 nginx: worker process
nobody 29287 29282 1 02:23 ? 00:00:00 nginx: worker process
nobody 29288 29282 2 02:23 ? 00:00:00 nginx: worker process
nobody 29289 29282 3 02:23 ? 00:00:00 nginx: worker process
nobody 29290 29282 1 02:23 ? 00:00:00 nginx: worker process
nobody 29291 29282 0 02:23 ? 00:00:00 nginx: cache manager process
nobody 29292 29282 0 02:23 ? 00:00:00 nginx: cache loader process
root 29294 29157 0 02:23 pts
/2
00:00:00
grep
nginx
[root@linux-node3 ~]
# lsof -i:80
COMMAND PID USER FD TYPE DEVICE SIZE
/OFF
NODE NAME
nginx 29282 root 6u IPv4 383819 0t0 TCP *:http (LISTEN)
nginx 29283 nobody 6u IPv4 383819 0t0 TCP *:http (LISTEN)
nginx 29284 nobody 6u IPv4 383819 0t0 TCP *:http (LISTEN)
nginx 29285 nobody 6u IPv4 383819 0t0 TCP *:http (LISTEN)
nginx 29286 nobody 6u IPv4 383819 0t0 TCP *:http (LISTEN)
nginx 29287 nobody 6u IPv4 383819 0t0 TCP *:http (LISTEN)
nginx 29288 nobody 6u IPv4 383819 0t0 TCP *:http (LISTEN)
nginx 29289 nobody 6u IPv4 383819 0t0 TCP *:http (LISTEN)
nginx 29290 nobody 6u IPv4 383819 0t0 TCP *:http (LISTEN)
|
9、測試session是否共享
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
[root@linux-node3 ~]
# cd /usr/local/tomcat1/webapps/ROOT/
[root@linux-node3 ROOT]
# mkdir tomcat-session
[root@linux-node3 ROOT]
# cd tomcat-session/
[root@linux-node3 tomcat-session]
# vim index.jsp
<%@ page contentType=
"text/html; charset=GBK"
%>
<%@ page
import
=
"java.util.*"
%>
<html><
head
><title>Cluster Test<
/title
><
/head
>
<body>
<%
//HttpSession
session = request.getSession(
true
);
System.out.println(session.getId());
out.println(
"<br> SESSION ID:"
+ session.getId()+
"<br>"
);
%>
<
/body
>
將上面的tomcat-session拷貝到tomcat2的同路徑下
[root@linux-node3 tomcat-session]
# cp -r ../tomcat-session /usr/local/tomcat2/webapps/ROOT/
|
本機綁定hosts進行訪問測試: 110.110.115.118 www.wangshibo.com
測試步驟(服務器上iptables防火牆開通相應web端口) a)訪問http://www.wangshibo.com/tomcat-session,顯示出Session ID值,說明nginx反向代理tomcat運行正常。 b)按F5刷新屢次,看看Session ID是否會變化。若是Session ID指一直不變,說明Session ID共享成功;反之,共享不成功! c)關閉其中一個tomcat實例,觀察頁面的Session ID是否有變化,若是Session ID一直不變,則表示Session ID已經共享到其餘tomcat實例上)了。
響應速度: MSM在Session管理時,Tomcat中會保持本地Session,往Memcached中的同步是異步完成的,因此訪問速度和普通模式沒什麼區別。 惟一有區別的是,tomcat實例關閉後的首次訪問時,響應速度會變慢,可是持續一小段時間後續訪問速度恢復正常。
-------------------------------------------------擴展------------------------------------------------------ 以上介紹了nginx+tomcat+memcached實現session共享集羣的操做記錄,下面再追加一些須要注意的東西:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
上面採用了效率最高的kryo序列化tomcat配置,固然還有其餘四種序列化tomcat的配置方法,分別是:
a)java默認序列化tomcat配置,conf
/context
.xml添加:
<Manager className=
"de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes=
"n1:192.168.100.208:11211 n2:192.168.100.208:11311"
lockingMode=
"auto"
sticky=
"false"
requestUriIgnorePattern=
".*\.(png|gif|jpg|css|js)$"
sessionBackupAsync=
"false"
sessionBackupTimeout=
"100"
transcoderFactoryClass=
"de.javakaffee.web.msm.JavaSerializationTranscoderFactory"
/>
lib下須要增長的jar包:
spymemcached-2.10.3.jar
memcached-session-manager-1.7.0.jar
memcached-session-manager-tc7-1.7.0.jar
b)javolution序列化tomcat配置,conf
/context
.xml添加:
<Manager className=
"de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes=
"n1:192.168.100.208:11211 n2:192.168.100.208:11311"
lockingMode=
"auto"
sticky=
"false"
requestUriIgnorePattern=
".*\.(png|gif|jpg|css|js)$"
sessionBackupAsync=
"false"
sessionBackupTimeout=
"100"
copyCollectionsForSerialization=
"true"
transcoderFactoryClass=
"de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
/>
lib下須要增長的jar包:
msm-javolution-serializer-cglib-1.3.0.jar
msm-javolution-serializer-jodatime-1.3.0.jar
spymemcached-2.10.3.jar
javolution-5.4.3.1.jar
msm-javolution-serializer-1.7.0.jar
memcached-session-manager-1.7.0.jar
memcached-session-manager-tc7-1.7.0.jar
c)xstream序列化tomcat配置,conf
/context
.xml添加:
<Manager className=
"de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes=
"n1:192.168.100.208:11211 n2:192.168.100.208:11311"
lockingMode=
"auto"
sticky=
"false"
requestUriIgnorePattern=
".*\.(png|gif|jpg|css|js)$"
sessionBackupAsync=
"false"
sessionBackupTimeout=
"100"
transcoderFactoryClass=
"de.javakaffee.web.msm.serializer.xstream.XStreamTranscoderFactory"
/>
lib下須要增長的jar包:
xmlpull-1.1.3.1.jar
xpp3_min-1.1.4c.jar
xstream-1.4.6.jar
msm-xstream-serializer-1.7.0.jar
spymemcached-2.10.3.jar
memcached-session-manager-1.7.0.jar
memcached-session-manager-tc7-1.7.0.jar
d)flexjson序列化tomcat配置,conf
/context
.xml添加:
<Manager className=
"de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes=
"n1:192.168.100.208:11211 n2:192.168.100.208:11311"
lockingMode=
"auto"
sticky=
"false"
requestUriIgnorePattern=
".*\.(png|gif|jpg|css|js)$"
sessionBackupAsync=
"false"
sessionBackupTimeout=
"100"
transcoderFactoryClass=
"de.javakaffee.web.msm.serializer.json.JSONTranscoderFactory"
/>
lib增長jar包
flexjson-3.1.jar
msm-flexjson-serializer-1.7.0.jar
spymemcached-2.10.3.jar
memcached-session-manager-1.7.0.jar
memcached-session-manager-tc7-1.7.0.jar
|
序列化tomcat配置中有關Manager各參數說明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
a)className
這個是必選項。可配置爲:
de.javakaffee.web.msm.MemcachedBackupSessionManager
或者
de.javakaffee.web.msm.DummyMemcachedBackupSessionManager
其中DummyMemcachedBackupSessionManager可用於測試環境,不須要真實存在memcached
b)memcachedNodes
這個是必選項。memcached的節點信息(多個節點使用空格或逗號分開),格式如:
memcachedNodes=
"n1:app01:11211,n2:app02:11211"
。
c)failoverNodes
這個是可選項,不能使用在non-sticky sessions模式。
故障轉移配置節點,多個使用空格或逗號分開,配置某個節點爲備份節點,當其餘節點都不可用時纔會存儲到備份節點,官方建議配置爲和tomcat同服務器的節點。
理由以下:
假若有兩臺服務器m1,m2,其中m1部署tomcat和memcached節點n1,m2部署memcached節點n2。
若是配置tomcat的failoverNodes值爲n2或者不配置,則當服務器m1掛掉後n1和tomcat中保存的session會丟失,而n2中未保存或者只保存了部分session,這就形成
部分用戶狀態丟失;
若是配置tomcat的failoverNodes值爲n1,則當m1掛掉後由於n2中保存了全部的session,因此重啓tomcat的時候用戶狀態不會丟失。
爲何n2中保存了全部的session? 由於failoverNodes配置的值是n1,只有當n2節點不可用時纔會把session存儲到n1,因此這個時候n1中是沒有保存任何session的。
d)lockingMode
這個是可選項,默認none,只對non-sticky有效。
當配置成node時,表示歷來不加鎖
當配置成all時,表示當請求時對Session鎖定,直到請求結束
當配置成auto時,表示對只讀的request不加鎖,對非只讀的request加鎖
e)requestUriIgnorePattern
這個是可選項,制定忽略那些請求的session操做,通常制定靜態資源如css,js一類的。
f)sessionBackupAsync
這個是可選項,默認
true
,是否異步的方式存儲到memcached。
j)sessionBackupTimeout
這個是可選項,默認100毫秒,異步存儲session的超時時間。即web工程對session的修改更新到memcache上的時間。
h)copyCollectionsForSerialization
這個是可選項,默認
false
。
i)transcoderFactoryClass
這個是可選項,默認值de.javakaffee.web.msm.JavaSerializationTranscoderFactory,制定序列化和反序列化數據到memcached的工廠類。
j)operationTimeout
這個是可選項,默認1000毫秒,memcached的操做超時時間。
k)backupThreadCount
這個是可選項,默認是cpu核心數,異步存儲session的線程數。
l)storageKeyPrefix
這個是可選項,默認值webappVersion,存儲到memcached的前綴,主要是爲了區分多個webapp共享session的狀況。可選值:靜態字符串、host、context、webappVersion,多個使用逗號分割。 、
m)sessionAttributeFilter
這個是可選項,經過正則表達式肯定那些session中的屬性應該被存儲到memcached。例子如:sessionAttributeFilter=
"^(userName|sessionHistory)$"
。
|
再說下stick和non-stick的工做流程:
1
2
3
4
5
|
Sticky 模式:
tomcat session爲主session,memcached爲備session。Request請求到來時,從memcached加載備session到tomcat (僅當tomcat jvmroute發生變化時,不然直接取tomcat session);Request請求結束時,將tomcat session更新至memcached,以達到主備同步之目的。
Non-Sticky模式:
tomcat session爲中轉session,memcached1爲主session,memcached2爲備session。Request請求到來時,從memcached 2加載備session到tomcat,(當容器中仍是沒有session則從memcached1加載主session到tomcat, 這種狀況是隻有一個memcached節點,或者有memcached1出錯時), Request請求結束時,將tomcat session更新至主memcached1和備memcached2,而且清除tomcat session 。以達到主備同步之目的。 多臺tomcat集羣時 須要選擇Non-Sticky模式,即sticky=
"false"
|
須要清除的是:
1
2
|
1)若是部署後,發現調試不成功,即session不共享,通常都是因爲memcached-session-manager-1.7.0.jar、memcached-session-manager-tc7-1.7.0.jar和msm-kryo-serializer-1.7.0.jar這三個jar包出問題。因此版本也很重要。
2)服務器之間的時間戳一致也很是重要,由於時間不一致將直接致使session過時。
|