0%

你一定不知道 如何在 Tomcat 集群中实现三种会话绑定

关于 Tomcat 系列其他文章的传送门

  1. 《 如何在 10 分钟内学会 Tomcat 8 》

  2. 《 干货分享 生产环境中如何为 Tomcat 配置反向代理和负载均衡 》

  3. 《 你一定不知道 如何在 Tomcat 集群中实现三种会话绑定 》     您当前所在位置



logo

会话绑定的三种方式

在 Tomcat 集群中,保持 session 的方式有以下三种:

  • session sticky:基于会话粘性;
    • 可以根据 source_ip 实现,如:
      • nginx 中的 ip_hash
      • haproxy 中的 source
      • lvs 中的 sh
    • 或使用 cookie 实现绑定,如:
      • nginx 中的 hash
      • haproxy 中的 cookie
  • session cluster:基于 session 复制集群,每个节点都保存 session 信息;
  • session server:使用一个专用的服务器保存 session,如 redis,memcached 等。

本文会逐一讲解以上 3 种会话绑定的实现方式。

一、配置基于 session sticky 的会话绑定

想要实现 session sticky 可以通过 source_ip 或 Cookie 的方式实现,使用 Cookie 可以控制的颗粒度比较精细,建议使用。

在 Nginx 中使用 Cookie 会话绑定要购买企业版,而 HAProxy 是可以免费使用的,之前已经介绍过配置方法,可以查看之前的博客。 《 从零玩转 HAProxy 》

本篇主要介绍如何通过 Apache 实现基于 Cookie 的 session sticky。

Apache 配置示例

Apache 中配置会话粘性的方法非常简单。

示例:

为了配置文件的规范整洁,建议在 /etc/httpd/conf.d 中新建子配置文件。

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
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
# 定义首部键的名称为 ROUTEID; path=/: 指明 Cookie 应用范围; ↑ 后端宕机后是否重新调度;

##- 定义后端组
<proxy balancer://tomcat>
BalancerMember http://10.0.0.2:8080 route=TomcatA loadfactor=1 # 为后端主机定义唯一标识
BalancerMember http://10.0.0.3:8080 route=TomcatB loadfactor=1 # loadfactor 位权重
ProxySet lbmethod=byrequests
ProxySet stickysession=ROUTEID # 设置定义会话绑定的首部名称。
</Proxy>

<VirtualHost *:80>
ServerName node1.monster.com
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tomcat/
ProxyPassReverse / balancer://tomcat/
<Location />
Require all granted
</Location>
</VirtualHost>

然后在 Tomcat 中配置好网页即可,不需要别的什么特殊配置,这里就不详细说明了。

主页测试文件可以使用这个 index.jsp

接下来重启 httpd 使配置生效,再使用浏览器访问时就会启用基于 Cookie 的 session sticky

可以看出,因为 Cookie 的存在,无论怎么刷新都会被调度至同一台主机。
如果把 Cookie 清理了或者更换其他浏览器,则会重新调度至新的后端并生成 Cookie。

apache

二、配置基于 session cluster 的会话绑定

Tomcat 自身支持使用 Tomcat Session Replication 来配置 session cluster,集群内的 Tomcat 节点可自动同步 session 信息。

tomcat_cluster

官方对集群的介绍

官网

Using the above configuration will enable all-to-all session replication using the DeltaManager to replicate session deltas. By all-to-all, we mean that every session gets replicated to all the other nodes in the cluster. This works great for smaller clusters, but we don’t recommend it for larger clusters — more than 4 nodes or so. Also, when using the DeltaManager, Tomcat will replicate sessions to all nodes, even nodes that don’t have the application deployed.
To get around these problem, you’ll want to use the BackupManager. The BackupManager only replicates the session data to one backup node, and only to nodes that have the application deployed. Once you have a simple cluster running with the DeltaManager, you will probably want to migrate to the BackupManager as you increase the number of nodes in your cluster.

一些重要的默认配置

  1. 复制集群使用多播地址 228.0.0.4
  2. 多播地址工作在 45564 端口,而端口和地址决定了主机是否在同一个集群;
  3. 多播地址使用 java.net.InetAddress.getLocalHost().getHostAddress() 配置,并确认不要使用 127.0.0.1
  4. TCP 4000-4100 的第一个可用套接字用来监听复制消息;
  5. 监听器使用 ClusterSessionListener 来配置;
  6. 拦截器的配置有两个
    • 校验 TCP 信息的完整性的 TcpFailureDetector
    • 消息分发拦截器 MessageDispatchInterceptor

配置文件模板

启用集群的方式,就是将下列配置放置于 <engine><host> 中,生效范围不同;

以下是官方提供的 集群配置模板,仅适用于 Tomcat 8 !!!

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
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">

// 定义使用哪个会话管理器,默认使用 DeltaManager
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false" // 定义当前节点关闭后,会话是否超时
notifyListenersOnReplication="true"/> // 定义复制时是否通知给侦听器

// 定义多播会话通信信道的一些参数
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
// 定义多播集群成员关系判定的一些参数
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500" // 定义节点成员每隔多久发一次心跳检测,单位毫秒
dropTime="3000"/> // 定义成员失去心跳多久后将其踢出集群,单位毫秒
// 定义接收器
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto" // 定义监听的地址,默认自动选出一个绑定
port="4000"
autoBind="100" // 多久自动绑定一次
selectorTimeout="5000" // 挑选出的地址的超时时间是多长
maxThreads="6"/> // 最大线程数
// 定义发送器
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className=" org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
// 定义拦截器
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
</Channel>

// 定义过滤器
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve" // 处理复制相关的报文
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> // JVM 的路由绑定器

// 定义部署器,自动同步新的部署文件到所有节点
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/" // 定义同步时的临时目录
deployDir="/tmp/war-deploy/" // 定义部署的目标目录
watchDir="/tmp/war-listen/" // 定义监控哪个目录的内容变化
watchEnabled="false"/> // 默认同步功能没有启用

// 定义侦听器,侦听集群内容资源变化
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

配置中的注意事项

要在 Tomcat 8 容器中运行 session 复制集群,应完成以下步骤:

  1. server.xml 中添加上述配置;
  2. 确认 IP 和 Port 不会发生冲突,集群会在 4000-4100 中自动找一个端口来监听;
  3. 网站配置文件 web.xml<distributable/> 配置必须存在;
  4. 确定 <Engine name="Catalina" jvmRoute="node01" > 中的 jvmRoute 参数和 workers.propertiesworker 相匹配;

虽然使用了 session 复制集群,但是还是建议同时启用 Cookie 绑定。

配置 Tomcat 复制集群步骤详解

先配置后端的 Tomcat

1、安装好 Tomcat 8

2、创建测试网站的目录 myapp

1
mkdir /webapps/myapp/WEB-INF -pv

3、创建首页测试文件

index.jsp

主机:Tomcat A10.0.0.12

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.monster.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("monster.com","monster.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>

主机:Tomcat B10.0.0.13

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page language="java" %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="blue">TomcatB.monster.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("monster.com","monster.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>

4、编辑 server.xml

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
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatA">   // 配置 jvmRoute="tomcatA"

//在 Engine 中插入如下 cluster 配置
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">

<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>


<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>

<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto" // 此处可以写 IP 地址
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>

<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className=" org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>

<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
</Channel>

<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>

<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

// 在默认的 Host 中添加 Context 别名
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="/myapp" docBase="/webapps/myapp" reloadble=""/>

5、从 /usr/local/tomcat/conf/ 下复制一份默认配置 web.xml 到 myapp 的 WEB-INF 目录下。

1
cp /usr/local/tomcat/conf/web.xml /webapps/myapp/WEB-INF

6、编辑 web.xml,在第一个 <servlet> 前添加以下行。

1
2
3
4
5
<distributable/>   # 这行是新加的
<servlet>
<servlet-name>default</servlet-name>
...
...

7、重启,tomcat 就配置好了。

再配置前端代理 Nginx

接下来安装前端的代理,这里以 Nginx 为例,也可以使用 HAProxy。

编辑 Nginx 的配置文件,在对应的上下文中添加如下配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
http {
...
...
upstream tomcat {
server 10.0.0.12:8080;
server 10.0.0.13:8080;
}

server {
...
...
location /myapp {
proxy_pass http://tomcat;
}
}
}

重载 Nginx 使配置生效,然后从浏览器访问 Nginx 的地址 http://192.168.50.11/myapp,可以看出虽然被调度至不同的后端,但是 session 信息没有变。

session

三、配置基于 session server 的会话绑定

这种架构会使用一个独立的 session server 来保存 session 信息,比如使用 Redis 或 Memcached,本文使用 Memcached 来演示。

Memcached 介绍

memcached

Memcached 是免费和开源,高性能,分布式的内存型键值存储系统,没有表的概念,所以在性能上比关系型数据库要快上不知道多少倍,但带来的缺点是因为结构太简单,基本没有什么多余的功能,比如主从复制、登录认证等,都需要通过智能客户端软件自己来实现,所以生产环境中还是建议使用 Redis。

缓存服务器分为 代理式旁路式,像 Varnish 就属于代理式缓存,而 Memcached 和 Redis 都属于旁路式缓存。

Memcached 已经被收录在 Base 仓库,可直接使用 yum 安装:

1
yum install memcached -y

启动服务

1
systemctl start memcached

Memcached 默认监听在 11211/tcp, 11211/udp

Memcached 配置

Memcached 可供配置的参数很少,都是直接通过命令行直接进行配置的,所以没有提供配置文件,可用参数:

  • -l:配置监听的地址;
  • -p:配置监听的 TCP 端口,默认 11211
  • -U:配置监听的 UDP 端口,默认 112110 代表不使用;
  • -u:定义使用的用户;
  • -s:配置监听的套接字;
  • -d:以守护方式运行;
  • -m:定义最大使用多大内存空间,超出后会使用 LRU 淘汰旧内存,默认 64MB
  • -M:定义最大使用多大内存空间,超出后会拒绝存放新数据;
  • -n:定义最小的存储空间单元从多少起步,默认 48
  • -f:定义增长因子,默认为 1.25
  • -c:最大并发连接数,默认 1024 个;
  • -t:使用几个线程,默认是 4 个,最好小于等于 CPU 的核心数。

可以通过修改 Unit File 文件来改变默认配置,Unit File 文件 /usr/lib/systemd/system/memcached.service

1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
Description=Memcached
Before=httpd.service
After=network.target

[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/memcached # 环境变量配置文件
ExecStart=/usr/bin/memcached -u $USER -p $PORT -m $CACHESIZE -c $MAXCONN $OPTIONS # 参数,变量来自环境变量配置文件

[Install]
WantedBy=multi-user.target

环境变量配置文件 /etc/sysconfig/memcached

1
2
3
4
5
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-t 4 -f 1.1" # 定义其他参数,这里手动定义了工作线程的数量和增长因子

连接至 Memcached

Memcached 的传输使用了 Memcached 协议,支持二进制格式和文本格式,默认使用文本格式,可以通过 telnet 连接至 Memcached,使用 stats 可以查看软件信息和一些统计数据。

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
-> # telnet 192.168.50.11 11211
Trying 192.168.50.11...
Connected to 192.168.50.11.
Escape character is '^]'.
stats
STAT pid 10282
STAT uptime 324
STAT time 1566812247
STAT version 1.4.15
STAT libevent 2.0.21-stable
STAT pointer_size 64
STAT rusage_user 0.006238
STAT rusage_system 0.015595
STAT curr_connections 10
STAT total_connections 13
STAT connection_structures 11
STAT reserved_fds 20
STAT cmd_get 0
STAT cmd_set 0
STAT cmd_flush 0
STAT cmd_touch 0
STAT get_hits 0
STAT get_misses 0
STAT delete_misses 0
STAT delete_hits 0
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 81
STAT bytes_written 1146
STAT limit_maxbytes 67108864
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT threads 4
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT bytes 0
STAT curr_items 0
STAT total_items 0
STAT expired_unfetched 0
STAT evicted_unfetched 0
STAT evictions 0
STAT reclaimed 0
END

Memcached 的控制数据的命令

储存:

  • <command name> <key> <flags> <exptime> <bytes> [noreply]\r\n

  • <command name>

    • set:无论如何都存储,数据不存在时存储,数据存在时更新;
    • add:当数据不存在时存储。
参数 含义
key key 关键字
flag 存储额外信息
exptime 数据保存时间,0 表示永远,单位秒
bytes 存储数据的字节数
noreply 要存储的数据
1
2
3
add mykey 0 0 5
testv
STORED # 表示已经存储完毕

读取:

  • get <key>*\r\n
1
2
3
4
get mykey
VALUE mykey 0 5
testv
END

删除:

  • delete <key> [noreply]\r\n

清空值:

  • flush:清空指定值;
  • flush_all:清空全部值。

查看状态:

  • stats\r\n:全部显示;
  • stats <args>\r\n 指定显示某一行。

自加和自减:

  • incr <key> <value> [noreply]\r\n or decr <key> <value> [noreply]\r\n

Memcached 管理工具:

  • memcached-tool 127.0.0.1

Memcached session manager

msm 介绍

我们可以把 session 的信息存储在单独的 Memcached 上,但是这样 Memcached 节点就成为了单点,存在 故障隐患。所以我们最少应该使用两台服务器来作为 Memcached,以保证高可用性,但是这又带来一个新问题,Memcached 自身支持的功能非常单一,主从复制、主备双活等等一概不支持,所以虽然使用了两台来储存 session 信息,但是这两台是完全独立的,一台如果宕机,其中的 session 信息就会全部丢失,为了解决这样的问题,就需要使用智能的客户端软件来实现,比如 msm

msm 全称是 memcache-session-manager,是一个 tomcat 的会话管理器,它将会话保存在 memcached 或 Redis 中,用于高可用性、可伸缩和容错的 web 应用程序。它支持粘性和非粘性配置。对于粘性会话(使用一主一备),支持会话故障转移,而非粘性会话是缺省值(使用双主双活,对于不同的请求,由不同的 tomcat 提供),如果遇到 memcached 崩溃,通过迁移会话进行故障转移,避免了单点故障。

msm 类库的安装

msm 的运行需要安装以下 3 种 jar 类库:

  • 会话管理器的类库 (session manager):用来管理 session 信息;
  • 驱动存储的类库:用来连接至存储,执行增删改查等操作;
  • 流式化的工具类库:使 K/V 序列化传输并保存的工具。

下面开始一步一步讲解 msm 类库的安装,注意:本教程仅适用于 Tomcat 8 !!!

按照官方安装文档的教程下载类库,并将下载好的 jar 包保存至 tomcat 的类库文件夹,本文使用的是 /usr/local/tomcat/lib

我把下载好的包整理在一起了,点这里可以打包下载。msm.zip

1
2
3
4
5
6
7
8
9
10
asm-5.2.jar
kryo-3.0.3.jar
kryo-serializers-0.45.jar
memcached-session-manager-2.3.2.jar
memcached-session-manager-tc8-2.3.2.jar
minlog-1.3.1.jar
msm-kryo-serializer-2.3.2.jar
objenesis-2.6.jar
reflectasm-1.11.9.jar
spymemcached-2.12.3.jar

配置 Tomcat 使用 msm

安装好 msm 的 jar 类库后,要想让 Tomcat 使用 msm,需要在 server.xml 配置文件中添加一些相关配置段。

而 msm 有两种工作方式,分别可以使后端的 Memcachde 实现 1 主 1 备或双主双活,配置方法略有不同,下面开始逐一介绍。

第 1 种 – 使用粘性会话,即 1 主 1 备

正常情况下只有主 memcached 节点在工作,当主节点宕机时,会启用备节点工作。当主节点恢复时会把工作抢回来,备节点开始闲置。

实验拓扑图:
sticky

实验步骤:

  1. 创建两个 Memcached 服务器 1 和 2,对应的主机名为 node1.monster.comnode2.monster.com,并启动服务 systemctl start memcached

  2. 创建两个 Tomcat 服务器,Tomcat A 和 Tomcat B,将 msm 的相关配置添加到每台的 server.xml 配置文件中,主页文件则使用这个 index.jsp,放置在 /webapps/myapp 中。

  3. 前端使用 Nginx 使用轮询反向代理到两个 Tomcat 服务器。

msm 的一些配置参数含义:

  • m1 是 Memcached 节点的别名,host1.yourdomain.com 为对应的主机名;
  • failoverNodes="m1":定义 m1 为故障转移节点,也就是备用节点;
  • requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$":忽略静态资源;
  • transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    • 定义使用哪一个流式化工具,本文使用 Kryo,如果使用其他的则将 Kryo 关键字替换为对应的名字即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatA"> // TomcatB 节点中应该是 TomcatB,其他参数保持一致
...
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="/myapp" docBase="/webapps/myapp" reloadble="">
// msm 的相关配置段
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="m1:node1.monster.com:11211,m2:node2.monster.com:11211"
failoverNodes="m1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
// msm 的相关配置段
...
</Context>
</Host>
</Engine>

确保启动了 Tomcat 和 Memcached 的服务,然后从浏览器访问测试主页,应该可以看到始终只有 m2 在工作,只有当 m2 宕机了,m1 才会工作,并且当 m2 恢复后,m1 又会闲置。

而最重要的是,在这期间,session 信息始终没有发生变化。

第 2 种 – 不使用粘性会话,即双主双活

当使用双主双活时,msm 会将两个 memcached 都作为主节点使用,当其中一台宕机时,会话被转移到另一活动节点。

实验环境和上面的一样,只不过现在两台 Memcached 都是主节点了。

关于 msm 的相关配置,编辑在 server.xml 中,与 1 主 1 备有一些不同:

一些配置参数的含义:

  • sticky="false":定义不使用粘性会话;
  • sessionBackupAsync="false":节点收到 session 数据会立即同步到其他节点。
  • lockingMode="uriPattern:/path1|/path2":指定哪些 path 启用会话锁定。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatA"> // TomcatB 节点中应该是 TomcatB,其他参数保持一致
...
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="/myapp" docBase="/webapps/myapp" reloadble="">
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="m1:node1.monster.com:11211,m2:node2.monster.com:11211"
sticky="false"
sessionBackupAsync="false"
lockingMode="uriPattern:/myapp"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
...
</Context>
</Host>
</Engine>

确保启动了 Tomcat 和 Memcached 的服务,然后从两个不同的浏览器,访问测试主页 http://192.168.50.11/myapp

可以看到两台 Memcached 同时在工作,m1 和 m2 同时在工作。

no_sticky

这时如果有一台宕机了,就会将会话转移至另一个节点。

而最重要的是,在这期间,session 信息始终没有发生变化。

使用 Redis 时不使用粘性会话的配置模板

当后端是 Redis 时使用的配置模板如下。

1
2
3
4
5
6
7
8
9
10
11
<Context>
...
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="redis://<password@>redis.example.com"
sticky="false"
sessionBackupAsync="false"
lockingMode="uriPattern:/path1|/path2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>

tom