Tomcat 通過 Memcached 實現 Session 會話共享
1、MSM 項目地址
Memcached-Session-Manager 項目地址 Github
Memcached-Session-Manager 項目地址 Google
2、準備工作
2.1 MSM 相關 jar 包下載
### 下載如下jar文件至各tomcat節點的tomcat安裝目錄下的lib目錄中
### 其中的${version}要換成你所需要的版本號
### tc${6,7,8}要換成與tomcat版本相同的版本號
# memcached-session-manager-${version}.jar
# memcached-session-manager-tc${6,7,8}-${version}.jar
# spymemcached-${version}.jar
# msm-javolution-serializer-${version}.jar
# javolution-${version}.jar
2.2 MSM 不同場景的相關 jar 包下載
MSM-Installation and Configuration-WIKI-PAGE-相關 jar 包下載
2.3 MSM 不同場景的配置模版
MSM-Installation and Configuration-WIKI-PAGE-配置模版查看
2.4 相關 jar 包下載
3、實驗拓撲
4、Tomcat 和 Memcached 部署
4.1 軟件安裝
### 安裝 Tomcat ###
# yum install tomcat.noarch tomcat-admin-webapps.noarch tomcat-docs-webapp.noarch tomcat-webapps.noarch -y
### 安裝 Memcached ###
# yum install memcached -y
4.2 Tomcat -1 配置
4.2.1Tomcat-1 增加的測試頁
[root@Tang-1 ~]# mkdir -pv /usr/local/tomcat/webapps/test/WEB-INF/{classes,lib}
[root@Tang-1 ~]# vim /usr/local/tomcat/webapps/test/index.jsp
[root@Tang-1 ~]# cat /usr/local/tomcat/webapps/test/index.jsp
<%@ page language="java" %>
<html>
<head><title>Tomcat-Tang-1</title></head>
<body>
<h1><font color="red">Tang-1</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("Tang","Tang"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
4.2.2 Tomcat-1 server-xml 文件配置
[root@Tang-1 ~]# vim /etc/tomcat/server.xml
<Engine name="Catalina" defaultHost="localhost" jvmRoute="Tomcat-Tang-1">
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="/test" docBase="/usr/local/tomcat/webapps/test" reloadable="true">
</Context>
</Host>
</Engine>
4.2.3 Tomcat-1 服務啓動
[root@Tang-1 ~]# systemctl start tomcat
[root@Tang-1 ~]# ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 100 :::8009 :::*
LISTEN 0 100 :::8080 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
LISTEN 0 1 ::ffff:127.0.0.1:8005 :::*
4.2.4 Tomcat-1 測試頁面訪問
4.3 Tomcat-2 配置
4.3.1 Tomcat-2 增加的測試頁
[root@Tang-2 ~]# mkdir -pv /usr/local/tomcat/webapps/test/WEB-INF/{classes,lib}
[root@Tang-2 ~]# vim /usr/local/tomcat/webapps/test/index.jsp
[root@Tang-2 ~]# cat /usr/local/tomcat/webapps/test/index.jsp
<%@ page language="java" %>
<html>
<head><title>Tomcat-Tang-2</title></head>
<body>
<h1><font color="purple">Tang-2</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("Tang","Tang"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
4.3.2 Tomcat-2 server-xml 文件配置
[root@Tang-2 ~]# vim /etc/tomcat/server.xml
<Engine name="Catalina" defaultHost="localhost" jvmRoute="Tomcat-Tang-2">
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="/test" docBase="/usr/local/tomcat/webapps/test" reloadable="true">
</Context>
</Host>
</Engine>
4.3.3 Tomcat-2 服務啓動
[root@Tang-2 ~]# systemctl start tomcat
[root@Tang-2 ~]# ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 100 :::8009 :::*
LISTEN 0 100 :::8080 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
LISTEN 0 1 ::ffff:127.0.0.1:8005 :::*
4.3.4 Tomcat-2 測試頁面訪問
4.4 Tomcat memcached 配置
4.4.1 Tomcat-1
[root@Tang-1 ~]# ipinfo
enp1s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.16.141.209 netmask 255.255.255.0 broadcast 172.16.141.255
[root@Tang-1 ~]# cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="128"
OPTIONS="-t 8 -f 1.1 -U 0"
[root@Tang-1 ~]# systemctl start memcached
[root@Tang-1 ~]# ss -tnlp | grep memcached
LISTEN 0 128 *:11211 *:* users:(("memcached",pid=9166,fd=46))
LISTEN 0 128 :::11211 :::* users:(("memcached",pid=9166,fd=47))
4.4.2 Tomcat-2
[root@Tang-2 ~]# ipinfo
enp1s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.16.141.209 netmask 255.255.255.0 broadcast 172.16.141.255
[root@Tang-2 ~]# cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="128"
OPTIONS="-t 8 -f 1.1 -U 0"
[root@Tang-2 ~]# systemctl start memcached
[root@Tang-2 ~]# ss -tnlp | grep memcached
LISTEN 0 128 *:11211 *:* users:(("memcached",pid=9166,fd=46))
LISTEN 0 128 :::11211 :::* users:(("memcached",pid=9166,fd=47))
5、Nginx 配置
5.1 conf 文件配置
[root@Tang ~]# ipinfo
enp1s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.16.141.252 netmask 255.255.255.0 broadcast 172.16.141.255
[root@Tang ~]# vim /etc/nginx/nginx.conf
http {
upstream tomcatservers {
server 172.16.141.209:8080;
server 172.16.141.253:8080;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
location / {
}
location /test/ {
proxy_pass http://tomcatservers;
}
}
}
[root@Tang ~]# systemctl start nginx
[root@Tang ~]# ss -tnlp | grep nginx
LISTEN 0 128 *:80 *:* users:(("nginx",pid=19610,fd=6),("nginx",pid=19609,fd=6),("nginx",pid=19608,fd=6),("nginx",pid=19607,fd=6),("nginx",pid=19606,fd=6))
LISTEN 0 128 :::80 :::* users:(("nginx",pid=19610,fd=7),("nginx",pid=19609,fd=7),("nginx",pid=19608,fd=7),("nginx",pid=19607,fd=7),("nginx",pid=19606,fd=7))
5.2 客戶端訪問
如上,在配置 memcached-session-manager 會話共享之前,訪問 http://172.16.141.252/test 的請求會輪詢負載到 tomcat-1 和 tomcat-2 兩個節點上,並且 session id 會隨着頁面的刷新而改變,即此時還沒有實現 session 會話共享。
6、Tomcat 通過 Memcached 實現 Session 會話共享
6.1 準備工作
- 把第二節中下載的相關 jar 包放置在各 Tomcat 節點的 Tomcat 安裝目錄下的 lib 目錄中。
- 下來進行序列化 Tomcat 配置,序列化 Tomca t配置的方法有很多種:java默認序列化tomcat 配置、javolution 序列化 tomcat 配置、xstream 序列化 tomcat 配置、flexjson 序列化 tomcat 配置和 kryo 序列化 tomca t配置。推薦使用 kryo 序列化 tomcat 的效率最高,所以這裏只介紹 kryo 序列化。
6.2 Tomcat 節點的 MSM 配置
[root@Tang-1 ~]# vim /etc/tomcat/server.xml
<Engine name="Catalina" defaultHost="localhost" jvmRoute="Tomcat-Tang-1">
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="/test" docBase="/usr/local/tomcat/webapps/test" reloadable="true">
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.16.141.209:11211,n2:172.16.141.253:11211"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
/>
</Context>
</Host>
</Engine>
[root@Tang-2 ~]# vim /etc/tomcat/server.xml
<Engine name="Catalina" defaultHost="localhost" jvmRoute="Tomcat-Tang-2">
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="/test" docBase="/usr/local/tomcat/webapps/test" reloadable="true">
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.16.141.209:11211,n2:172.16.141.253:11211"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
/>
</Context>
</Host>
</Engine>
6.3 參數說明
故障轉移配置節點(failoverNodes),不能使用在Non-Sticky模式,多個使用空格或逗號分開,配置某個節點爲備份節點。當其他節點都不可用時纔會存儲到備份節點,適用於sticky模式(即一臺tomcat,多臺memcached)
-
memcachedNodes:必選項,memcached的節點信息,多個memcached節點,中間需要使用空格
-
failoverNodes=“n2”:表示當前 session 保持到 n1 的 memcached 節點上
## 當其他節點都不可用時纔會存儲到備份節點,官方建議配置爲和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的
-
lockingMode:可選值,默認none,只對 non-sticky 有效
-
requestUriIgnorePattern:可選值,制定忽略那些請求的 session 操作,一般制定靜態資源,如 css,js 一類的
-
sessionBackupAsync:可選值,默認 true,是否異步的方式存儲到 memcached
-
sessionBackupTimeout:可選項,默認100毫秒,異步存儲 session 的超時時間
6.4 重啓 Tomcat 服務後,進行頁面訪問
- 1、訪問http://172.16.141.252,按 ctrl+F5 強刷頁面,發現 session 信息會變,但是 session id 不會改變,說明 session 實現了共享
- 2、關閉 Mem-node1 節點的 memcached 服務,繼續訪問頁面,發現 session id 保存到了n2 這個 memcached 節點上了,但是 session id 任然沒有改變,說明 session 已共享. 也就是說,關閉 memcached 集羣中的任意一個節點訪問頁面,session id 都不會改變.即可以實現 memcached 故障轉移
- 3、關閉 tomcat-node1 和 tomcat-node2 中的任意一個節點的 tomcat 服務,繼續訪問頁面,發現前端從 nginx 負載過來的請求達到未關閉的 tomcat 節點上,session id 都不會改變,依然共享中!即可以實現 tomcat 故障轉移
- 4、特別提示:如果memcached session manager的會話共享配置後,重啓tomcat服務沒有報錯,但是訪問頁面的時候報錯,頁面訪問失敗,如下在logs/catalina.out日誌裏發現的錯誤:
SEVERE [http-nio-8080-exec-1] org.apache.coyote.http11.AbstractHttp11Processor.process Error processing request java.lang.NoSuchFieldError: attributes