tomcat session复制及session共享技术(普通)
前言:
为什么要做session复制或共享
实现Session复制或Session共享的目的是为了在多个Tomcat实例之间实现Session的无缝转移和共享,以提供更高的可伸缩性、负载均衡和容错性。以下是一些原因:
- 高可用性和容错性:通过复制或共享Session,当一个Tomcat实例发生故障或停机时,其他实例可以接管并继续处理用户请求,而不会丢失Session数据。这确保了应用程序的高可用性和容错性。
- 负载均衡:当有多个Tomcat实例运行时,Session复制或共享可以实现负载均衡。用户的请求可以分散到不同的实例上,提高系统的整体性能和吞吐量。
- 无状态化应用设计:通过将Session数据从应用服务器中移出,可以使应用程序变得更加无状态化。这意味着每个请求可以独立处理,不依赖于特定的服务器状态,从而提高应用程序的可扩展性。
- 保持用户会话状态:通过Session复制或共享,用户的会话状态可以在多个请求之间得到保持。这对于需要跨页面或多个请求保持用户身份、购物车信息、用户首选项等状态非常重要。
session 复制
1、环境
服务 | ip |
---|---|
nginx | 192.168.96.100 |
tomcat1 | 192.168.96.252 |
tomcat2 | 192.168.96.253 |
2、准备工作
1、主机名配置
2、防火墙、selinux关闭
3、时间同步
4、做本地解析
3、配置
在server.xml中配置,所有tomcat实例
<!-- 在配置文件中找到Engine行,在标签内添加jvmRoute,并在下方添加内容 -->
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
<!-- jvmRoute的内容是本机本地解析的主机名 -->
<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="192.168.96.252"
<!-- 本地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>
web.xml中设置
vim /usr/local/tomcat/webapps/ROOT/WEB-INF/web.xml
<display-name>Welcome to Tomcat</display-name> # 再此行下面添加下一行的内容
<distributable/>
4、配置测试页面
vim /usr/local/tomcat/webapps/ROOT/session.jsp
Session_ID: <%= session.getId() %><BR>
Session_Port: <%= request.getServerPort() %><BR>
Session_URL: <%= request.getRequestURL() %><BR>
<% out.println("This tomcat server 192.168.1.101");%>
重启tomcat
5、访问测试
6、个人看法
官方文档: https://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html
官方建议,不超过四个节点可以使用这个方法,因为他是all-to-all的模式,频繁的广播session信息会造成负载过高
配置tomcat session共享(基于redis)
前言:
为什么要做session复制或共享
实现Session复制或Session共享的目的是为了在多个Tomcat实例之间实现Session的无缝转移和共享,以提供更高的可伸缩性、负载均衡和容错性。以下是一些原因:
- 高可用性和容错性:通过复制或共享Session,当一个Tomcat实例发生故障或停机时,其他实例可以接管并继续处理用户请求,而不会丢失Session数据。这确保了应用程序的高可用性和容错性。
- 负载均衡:当有多个Tomcat实例运行时,Session复制或共享可以实现负载均衡。用户的请求可以分散到不同的实例上,提高系统的整体性能和吞吐量。
- 无状态化应用设计:通过将Session数据从应用服务器中移出,可以使应用程序变得更加无状态化。这意味着每个请求可以独立处理,不依赖于特定的服务器状态,从而提高应用程序的可扩展性。
- 保持用户会话状态:通过Session复制或共享,用户的会话状态可以在多个请求之间得到保持。这对于需要跨页面或多个请求保持用户身份、购物车信息、用户首选项等状态非常重要。
1、环境
服务 | ip | PORT |
---|---|---|
tomcat1 | 192.168.1.101 | 8080 |
tomcat2 | 192.168.1.101 | 8081 |
Tomcat3 | 192.168.1.101 | 8082 |
2、准备工作
1、主机名配置
2、防火墙、selinux关闭
3、时间同步
4、做本地解析
3、修改server.xml
[root@bogon ~]# vim /data/application/tomcat1/conf/server.xml
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource name="bean/redisson"
auth="Container"
factory="org.redisson.JndiRedissonFactory"
configPath="${catalina.base}/conf/redisson.yaml"
closeMethod="shutdown"/>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
4、修改context.xml
[root@bogon ~]# vim /data/application/tomcat1/conf/context.xml
<ResourceLink name="bean/redisson"
global="bean/redisson"
type="org.redisson.api.RedissonClient" />
<Manager className="org.redisson.tomcat.JndiRedissonSessionManager"
readMode="REDIS"
jndiName="bean/redisson" />
5、新增redisson配置文件 tomcat/conf/redisson.yaml
# 如果redis是单独安装的,将address地址修改为对应主机地址
[root@bogon ~]# vim /data/application/tomcat1/conf/redisson.yaml
singleServerConfig:
idleConnectionTimeout: 10000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
password: null
subscriptionsPerConnection: 5
clientName: null
address: "redis://127.0.0.1:6379"
subscriptionConnectionMinimumIdleSize: 1
subscriptionConnectionPoolSize: 50
connectionMinimumIdleSize: 24
connectionPoolSize: 64
database: 0
dnsMonitoringInterval: 5000
threads: 16
nettyThreads: 32
codec: !<org.redisson.codec.MarshallingCodec> {}
transportMode: "NIO"
6、下载并复制2个Jar包到Tomcat Lib目录中
[root@bogon ~]# wget https://repo1.maven.org/maven2/org/redisson/redisson-all/3.22.0/redisson-all-3.22.0.jar
[root@bogon ~]# wget https://repo1.maven.org/maven2/org/redisson/redisson-tomcat-8/3.22.0/redisson-tomcat-8-3.22.0.jar
[root@bogon ~]# cp redisson-all-3.22.0.jar /data/application/tomcat1/lib/
[root@bogon ~]# cp redisson-tomcat-8-3.22.0.jar /data/application/tomcat1/lib/
7、 安装redis
[root@bogon ~]# wget http://download.redis.io/releases/redis-5.0.10.tar.gz ---下载redis
[root@bogon ~]# tar xzf redis-5.0.10.tar.gz -C /data/application/ ---解压
[root@bogon ~]# cd /data/application/
[root@bogon application]# mv redis-5.0.10/ redis
[root@bogon application]# cd redis/
[root@bogon redis]# yum install -y gcc make #安装编译工具
[root@bogon redis]# make
注:如果报错请将刚才解压的安装包删除掉,再次重新解压并进行make安装即可。
[root@bogon redis]# cp redis.conf redis.conf.bak
[root@bogon redis]# vim redis.conf ---修改如下
bind 0.0.0.0 #只监听内网IP
daemonize yes #开启后台模式将on改为yes
timeout 300 #连接超时时间
port 6379 #端口号
dir /data/application/redis/data #本地数据库存放持久化数据的目录该目录-----需要存在
pidfile /var/run/redis_6379.pid #定义pid文件
logfile /var/log/redis.log #定义log文件
创建存放数据的目录
[root@bogon redis]# mkdir /data/application/redis/data
配置redis为systemctl启动
[root@bogon redis]# cd /lib/systemd/system
[root@bogon system]# vim redis.service
[Unit]
Description=Redis
After=network.target
[Service]
ExecStart=/data/application/redis/src/redis-server /data/application/redis/redis.conf --daemonize no
ExecStop=/data/application/redis/src/redis-cli -h 127.0.0.1 -p 6379 shutdown
[Install]
WantedBy=multi-user.target
=====================
参数详解:
• [Unit] 表示这是基础信息
• Description 是描述
• After 是在那个服务后面启动,一般是网络服务启动后启动
• [Service] 表示这里是服务信息
• ExecStart 是启动服务的命令
• ExecStop 是停止服务的指令
• [Install] 表示这是是安装相关信息
• WantedBy 是以哪种方式启动:multi-user.target表明当系统以多用户方式(默认的运行级别)启动时,这个服务需要被自动运行。
===================
启动服务:
[root@bogon system]# systemctl daemon-reload
[root@bogon system]# systemctl start redis.service
8、配置nginx负载均衡
[root@bogon ~]# cd /etc/yum.repos.d/
[root@bogon yum.repos.d]# vim nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
[root@bogon yum.repos.d]# yum install yum-utils -y
[root@bogon yum.repos.d]# yum install nginx -y
# 配置负载均衡器
# 备份原配置文件并修改
[root@bogon ~]# cd /etc/nginx/conf.d/
[root@bogon conf.d]# cp default.conf default.conf.bak
[root@bogon conf.d]# mv default.conf tomcat.conf
[root@bogon conf.d]# vim tomcat.conf
upstream testweb {
server 192.168.1.101:8081 weight=1 max_fails=1 fail_timeout=2s;
server 192.168.1.101:8082 weight=1 max_fails=1 fail_timeout=2s;
server 192.168.1.101:8083 weight=1 max_fails=1 fail_timeout=2s;
}
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/proxy.access.log main;
location / {
proxy_pass http://testweb;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
启动nginx
[root@bogon ~]# systemctl start nginx
9、配置测试页面
[root@bogon ~]# vim /data/application/tomcat1/webapps/ROOT/session.jsp
Session_ID: <%= session.getId() %><BR>
Session_Port: <%= request.getServerPort() %><BR>
Session_URL: <%= request.getRequestURL() %><BR>
<% out.println("This tomcat server 192.168.1.101");%>