使用Nginx、Redis集群实现Tomcat集群负载均衡,session共享

一、配置多个Tomcat同时运行html

1.一、修改环境变量 将tomcat 复制两份出来node

#将以前解压的tomcat文件夹直接复制并重命名为‘apache-tomcat_2’、‘apache-tomcat_3’
cp -r apache-tomcat apache-tomcat_2
cp -r apache-tomcat apache-tomcat_3
复制代码

修改环境变量,介入以下内容nginx

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

复制代码

保存退出,使配置文件当即生效。web

source /etc/profile
复制代码

1.二、修改 对应tomcat中的 catalina.sh,添加环境变量redis

第二个tomcat为例spring

vi catalina.sh
复制代码
# 修改 和 /etc/profile 中的 变量相同
export CATALINA_BASE=$CATALINA_BASE_2
export CATALINA_HOME=$CATALINA_HOME_2
复制代码

1.三、修改conf下配置文件 server.xml数据库

上面三处的端口修改一下便可,这样多台tomcat就能够同时运行了。apache

二、使用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.一、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.二、Tomcat-Redis-Session_manager

使用Tomcat-redis-session-manager来实现Tomcat集群部署中的Session共享,这种方式能够实现,可是须要本身去编译源码,还须要修改tomcat 的配置文件,比较繁琐,因此不是很推荐。

3.三、spring session

spring-session在无需绑定web容器的状况下提供对集群session的支持。并提供对如下状况的透明集成:

  • HttpSession:允许替换web容器的HttpSession
  • WebSocket:使用WebSocket通讯时,提供Session的活跃
  • WebSession:允许以应用中立的方式替换webflux的webSession

3.四、在springboot中如何实现:

1、springboot 集成

一、添加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>
复制代码

二、添加@EnableRedisHttpSession来开启spring session支持,配置以下:

@Configuration
//开启spring session支持
@EnableRedisHttpSession
public class RedisSessionConfig {
}

复制代码

三、由于以前弄了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();
    }
复制代码

这样基本算是完事了,将项目打包进行测试

四、测试,为了方便就不放到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。

相关文章
相关标签/搜索