使用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。

相關文章
相關標籤/搜索