1、配置多个Tomcat同时运行
1.1、修改环境变量 将tomcat 复制两份出来
#将之前解压的tomcat文件夹直接复制并重命名为‘apache-tomcat_2’、‘apache-tomcat_3’
cp -r apache-tomcat apache-tomcat_2
cp -r apache-tomcat apache-tomcat_3
复制代码
修改环境变量,介入如下内容
vi /etc/profile
复制代码
######### tomcat 1 ###########
CATALINA_BASE=/usr/local/tomcat/apache-tomcat
CATALINA_HOME=/usr/local/tomcat/apache-tomcat
TOMCAT_HOME=/usr/local/tomcat/apache-tomcat
export CATALINA_BASE CATALINA_HOME TOMCAT_HOME
########## tomcat 2 ##########
CATALINA_BASE_2=/usr/local/tomcat/apache-tomcat_2
CATALINA_HOME_2=/usr/local/tomcat/apache-tomcat_2
TOMCAT_HOME_2=/usr/local/tomcat/apache-tomcat_2
export CATALINA_BASE_2 CATALINA_HOME_2 TOMCAT_HOME_2
########## tomcat 3 ###########
CATALINA_BASE_3=/usr/local/tomcat/apache-tomcat_3
CATALINA_HOME_3=/usr/local/tomcat/apache-tomcat_3
TOMCAT_HOME_3=/usr/local/tomcat/apache-tomcat_3
export CATALINA_BASE_3 CATALINA_HOME_3 TOMCAT_HOME_3
复制代码
保存退出,使配置文件立即生效。
source /etc/profile
复制代码
1.2、修改 对应tomcat中的 catalina.sh,添加环境变量
第二个tomcat为例
vi catalina.sh
复制代码
# 修改 和 /etc/profile 中的 变量相同
export CATALINA_BASE=$CATALINA_BASE_2
export CATALINA_HOME=$CATALINA_HOME_2
复制代码
1.3、修改conf下配置文件 server.xml
上面三处的端口修改一下即可,这样多台tomcat就可以同时运行了。
2、使用Nginx搭建tomcat集群
这个主要就是在配置文件,简单的配置就能达到负载均衡的效果
#upstream设置,设置代理服务器(负载均衡池),默认的负载均衡方式是轮询,另外一种是ip_hash
upstream mynginx{
#想要负载的服务器地址列表
server 192.0.0.179:8088;
server 192.0.0.179:8089;
server 192.0.0.179:8090;
}
server {
listen 8888;
server_name 192.0.0.179;
location / {
root html;
index index.html index.htm;
add_header backendIP $upstream_addr;
proxy_pass http://mynginx;#注意要与定义的upstream模块名称相同
}
}
复制代码
这样直接访问地址:192.0.0.179:8888 , 就可以根据轮询 的情况给我们分发到定义的服务器列表中的一个。
但是这时就会出现一个问题,这样同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,就会出现很多问题,比如说最常见的登录状态
3、解决办法
在网上也看到了不少的解决办法,这里也简单的说一下
3.1、ip_hash:ip_hash技术能够将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session
ip_hash是在upstream配置中定义的
upstream mynginx{
#想要负载的服务器地址列表
server 192.0.0.179:8088;
server 192.0.0.179:8089;
server 192.0.0.179:8090;
ip_hash;
}
复制代码
ip_hash是容易理解的,但是因为仅仅能用ip这个因子来分配后端,因此ip_hash是有缺陷的,并不能很好的体现集群的优势
3.2、Tomcat-Redis-Session_manager
使用Tomcat-redis-session-manager来实现Tomcat集群部署中的Session共享,这种方式可以实现,但是需要自己去编译源码,还需要修改tomcat 的配置文件,比较繁琐,所以不是很推荐。
3.3、spring session
spring-session在无需绑定web容器的情况下提供对集群session的支持。并提供对以下情况的透明集成:
- HttpSession:容许替换web容器的HttpSession
- WebSocket:使用WebSocket通信时,提供Session的活跃
- WebSession:容许以应用中立的方式替换webflux的webSession
3.4、在springboot中如何实现:
一、springboot 集成
1、添加Maven依赖:
<!--spring boot 与redis应用基本环境配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring session 与redis应用基本环境配置,需要开启redis后才可以使用,不然启动Spring boot会报错 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
复制代码
2、添加@EnableRedisHttpSession来开启spring session支持,配置如下:
@Configuration
//开启spring session支持
@EnableRedisHttpSession
public class RedisSessionConfig {
}
复制代码
3、因为之前弄了redis集群,这里也可以配合使用,无奈之前挖了好多坑,也是好不容易才填上。。。。。。
如果是单纯的使用springsession,这里已经基本完成了,但是.......之前搞了shiro,session的管理已经交给了 shiro管理,这里还得重新倒腾一下,还要让shiro使用redis集群进行工作
将之前的shiro+redis缓存插件更换成‘3.1.0’ 版本,shiro-redis 3.1.0 开始支持redis集群配置
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.1.0</version>
</dependency>
复制代码
在贴一下相关的配置文件:
redis:
database: 0 # Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
# host: 127.0.0.1
# port: 6379
# redis.cluster
password:
cluster:
nodes: 192.0.0.179:7001,192.0.0.179:7002,192.0.0.179:7003,192.0.0.179:7004,192.0.0.179:7005,192.0.0.179:7006
lettuce:
pool:
#最大连接数
max-active: 1000
#最大阻塞等待时间(负数表示没限制)
max-wait: -1
#最大空闲
max-idle: 1000
#最小空闲
min-idle: 100
#连接超时时间
timeout: 1000
# 这里需要注意如果没有集成shiro,应该是要指定一下的,具体没试过。。
#session:
# store-type: redis
复制代码
修改之前的ShiroConfig,将RedisManager更换为RedisClusterManager,一些使用到RedisManager方法的地方直接替换成RedisClusterManager
#注入配置文件pojo
@Autowired
private RedisConf2 properties2;
---------------------------------
@Bean
public RedisClusterManager redisClusterManager(){
RedisClusterManager redisClusterManager = new RedisClusterManager();
redisClusterManager.setHost(properties2.getNodes());
return redisClusterManager;
}
复制代码
这里的host可以直接获取配置文件redis节点的配置,从而更加方便灵活
#配置文件读取
@Configuration
public class RedisConf2 {
@Value("${spring.redis.cluster.nodes}")
private String nodes;
public String getNodes() {
return nodes;
}
public void setNodes(String nodes) {
this.nodes = nodes;
}
}
复制代码
配置文件的读取方式有几种,可以根据自己的实际情况来定,我这里是单独抽象了一个pojo,在读取配置参数的地方通过‘ @Autowired’ 注入即可
这里还有一个需要注意的地方,这样直接启动会报错,配置文件读取不到,在网上找了很久解决方案,找到了比较简单的一个,修改shiro的getLifecycleBeanPostProcessor 方法,加上static,让其变成静态方法
@Bean
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
复制代码
这样基本算是完事了,将项目打包进行测试
4、测试,为了方便就不放到nginx里启动了,直接打包在本地用不同端口启动
清空redis:
192.0.0.179:7002> flushall
OK
192.0.0.179:7002> keys *
(empty list or set)
192.0.0.179:7002>
复制代码
第一个负责存入session
第二个负责读取session
再看一下redis,session信息已经存进去了
知识点:sessionid是一个会话的key,浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应。tomcat生成的sessionid叫做jsessionid。 session在访问tomcat服务器HttpServletRequest的getSession(true)的时候创建,tomcat的ManagerBase类提供创建sessionid的方法:随机数+时间+jvmid; 存储在服务器的内存中,tomcat的StandardManager类将session存储在内存中,也可以持久化到file,数据库,memcache,redis等。客户端只保存sessionid到cookie中,而不会保存session,session销毁只能通过invalidate或超时,关掉浏览器并不会关闭session。