1. 程式人生 > >Nginx+Tomcat搭建集群環境

Nginx+Tomcat搭建集群環境

Java開發 Tomcat Nginx 集群架構 單機部署多個Tomcat實例

集群概述與架構介紹

Tomcat集群能帶來什麽:

  • 提高服務的性能,例如計算處理能力、並發能力等,以及實現服務的高可用性
  • 提供項目架構的橫向擴展能力,增加集群中的機器就能提高集群的性能

Tomcat集群實現方式:

  • Tomcat集群的實現方式有多種,最簡單的就是通過Nginx負載進行請求轉發來實現

Tomcat單機架構圖:
技術分享圖片

可能看了上面的Tomcat單機的架構圖後,會 ”想當然“ 的覺得Tomcat集群架構是這樣子的:
技術分享圖片

這種 ”想當然“ 的Tomcat集群會帶來什麽問題:

  • Session登錄信息存儲及讀取的問題
  • 服務器定時任務並發的問題
  • ......

所以架構的演進並不是 ”想當然“ 的那麽簡單,當我們的架構隨著業務的需求進行演進時,就可能會發生代碼上的改動,以及其他各方面配置及機器的改動,並不是單純的增加Tomcat機器就行了。因為架構的演進都不是一蹴而就的,編程是一個遇見問題解決問題的過程,所以我們不可能一下子就設計出一個完美的架構,而且也不存在完美的架構,只有合適的架構。

常見的Tomcat集群解決方案:

  • 采用 nginx 中的 ip hash policy 來保持某個ip始終連接在某一個機器上
    • 優點:可以不改變現有的技術架構,直接實現橫向擴展,省事。但是缺陷也很明顯,在實際的生產環境中,極少使用這種方式
    • 缺點:1.單止服務器請求(負載)不均衡,這是完全依賴 ip hash 的結果。2.客戶機ip動態變化頻繁的情況下,無法進行服務,因為可能每次的ip hash都不一樣,就無法始終保持只連接在同一臺機器上。
  • 采用redis或memchche等nosql數據庫,實現一個緩存session的服務器,當請求過來的時候,所有的Tomcat Server都統一往這個服務器裏讀取session信息。這是企業中比較常用的一種解決方案,所以大致的Tomcat集群的架構圖如下:

技術分享圖片


單機部署多個Tomcat實例(Linux)

由於考慮到在學習時,可能沒有足夠的機器資源去用多臺機器部署多個Tomcat實例,所以本節將簡單介紹一下如何在Linux系統環境下,單機部署多個Tomcat實例。多機就不介紹了,因為多機就是一臺機器安裝一個Tomcat就行了,不需要做額外的更改。

1.到Tomcat官網中,復制Tomcat的下載鏈接進行下載並解壓到相應的目錄下:

[root@study-01 /usr/local/src]# wget http://mirrors.hust.edu.cn/apache/tomcat/tomcat-9/v9.0.7/bin/apache-tomcat-9.0.7.tar.gz
[root@study-01 /usr/local/src]# tar -zxvf apache-tomcat-9.0.7.tar.gz -C /usr/local/

2.安裝好Tomcat後,將Tomcat目錄拷貝多份出來。並更改一下目錄名稱:

[root@study-01 /usr/local]# cp -r apache-tomcat-9.0.7 ./tomcat9-02
[root@study-01 /usr/local]# mv apache-tomcat-9.0.7 ./tomcat9-01

3.配置環境變量:

[root@study-01 ~]# vim /etc/profile  # 在文件末尾增加如下內容
export CATALINA_BASE=/usr/local/tomcat9-01
export CATALINA_HOME=/usr/local/tomcat9-01
export TOMCAT_HOME=/usr/local/tomcat9-01

export CATALINA_2_BASE=/usr/local/tomcat9-02
export CATALINA_2_HOME=/usr/local/tomcat9-02
export TOMCAT_2_HOME=/usr/local/tomcat9-02
[root@study-01 ~]# source /etc/profile  # 使配置文件生效

4.第一個Tomcat不需要動,只需要修改第二個Tomcat的相關配置,首先編輯第二個Tomcat安裝目錄中bin目錄下的catalina.sh文件:

[root@study-01 ~]# cd /usr/local/tomcat9-02/bin/
[root@study-01 /usr/local/tomcat9-02/bin]# vim catalina.sh  # 找到如下那行註釋,在該註釋下,增加兩行配置
# OS specific support.  $var _must_ be set to either true or false.
export CATALINA_BASE=$CATALINA_2_BASE
export CATALINA_HOME=$CATALINA_2_HOME
[root@study-01 /usr/local/tomcat9-02/bin]# 

5.然後編輯第二個Tomcat安裝目錄中conf目錄下的server.xml文件,在該文件中需要修改三個端口:

[root@study-01 /usr/local/tomcat9-02/bin]# cd ../conf/
[root@study-01 /usr/local/tomcat9-02/conf]# vim server.xml
# 第一個端口,Server port節點端口
<Server port="9005" shutdown="SHUTDOWN">

# 第二個端口,Connector port節點端口,也即是Tomcat訪問端口
<Connector port="9080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" URIEncoding="UTF-8" />

# 第三個端口,Connector port節點端口
<Connector port="9009" protocol="AJP/1.3" redirectPort="8443" />        
[root@study-01 /usr/local/tomcat9-02/conf]#     

6.修改完成後,分別進入兩個Tomcat的bin目錄,執行腳本啟動Tomcat:

# 啟動Tomcat02
[root@study-01 /usr/local/tomcat9-02/conf]# cd ../bin/
[root@study-01 /usr/local/tomcat9-02/bin]# ./startup.sh 
Using CATALINA_BASE:   /usr/local/tomcat9-02
Using CATALINA_HOME:   /usr/local/tomcat9-02
Using CATALINA_TMPDIR: /usr/local/tomcat9-02/temp
Using JRE_HOME:        /usr/local/jdk1.8
Using CLASSPATH:       /usr/local/tomcat9-02/bin/bootstrap.jar:/usr/local/tomcat9-02/bin/tomcat-juli.jar
Tomcat started.
# 啟動Tomcat01
[root@study-01 /usr/local/tomcat9-02/bin]# cd ../../tomcat9-01/bin/
[root@study-01 /usr/local/tomcat9-01/bin]# ./startup.sh 
Using CATALINA_BASE:   /usr/local/tomcat9-01
Using CATALINA_HOME:   /usr/local/tomcat9-01
Using CATALINA_TMPDIR: /usr/local/tomcat9-01/temp
Using JRE_HOME:        /usr/local/jdk1.8
Using CLASSPATH:       /usr/local/tomcat9-01/bin/bootstrap.jar:/usr/local/tomcat9-01/bin/tomcat-juli.jar
Tomcat started.
[root@study-01 /usr/local/tomcat9-01/bin]# 

啟動完成後,檢查監聽的端口號及進程:

[root@study-01 ~]# netstat -lntp |grep java
tcp6       0      0 :::8009                 :::*                    LISTEN      2846/java           
tcp6       0      0 127.0.0.1:9005          :::*                    LISTEN      2784/java           
tcp6       0      0 :::8080                 :::*                    LISTEN      2846/java           
tcp6       0      0 :::9009                 :::*                    LISTEN      2784/java           
tcp6       0      0 :::9080                 :::*                    LISTEN      2784/java           
tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      2846/java           
[root@study-01 ~]# ps aux |grep java
root       2784  5.6  1.5 7105356 123956 pts/0  Sl   06:24   0:06 /usr/local/jdk1.8/bin/java -Djava.util.logging.config.file=/usr/local/tomcat9-02/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat9-02/bin/bootstrap.jar:/usr/local/tomcat9-02/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat9-02 -Dcatalina.home=/usr/local/tomcat9-02 -Djava.io.tmpdir=/usr/local/tomcat9-02/temp org.apache.catalina.startup.Bootstrap start
root       2846  6.5  1.4 7105356 119712 pts/0  Sl   06:24   0:05 /usr/local/jdk1.8/bin/java -Djava.util.logging.config.file=/usr/local/tomcat9-01/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat9-01/bin/bootstrap.jar:/usr/local/tomcat9-01/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat9-01 -Dcatalina.home=/usr/local/tomcat9-01 -Djava.io.tmpdir=/usr/local/tomcat9-01/temp org.apache.catalina.startup.Bootstrap start
root       2904  0.0  0.0 112680   976 pts/0    S+   06:25   0:00 grep --color=auto java
[root@study-01 ~]# 

最後在瀏覽器上訪問兩個不同的端口,看看是否能訪問到Tomcat默認的首頁。如下:
技術分享圖片
技術分享圖片

至此,我們的單機部署多個Tomcat實例就完成了,如果想繼續部署,依照此法繼續即可。

註:不同的Tomcat實例使用的端口號在系統中必須不能重復,必須是系統沒有使用的端口才行,不然會產生端口沖突。


Nginx負載均衡配置,常用策略,場景及特點簡介

Nginx負載均衡配置及策略:

  • 輪詢(默認)

    • 優點:實現簡單
    • 缺點:不考慮每臺服務器的處理能力
    • 配置示例如下:
      upstream www.xxx.com {
      # 需要負載的server列表
      server www.xxx.com:8080;
      server www.xxx.com:9080;
      }
  • 權重,使用的較多的策略
    • 優點:考慮了每臺服務器處理能力的不同,哪臺機器性能高就給哪臺機器的權重高一些
    • 配置示例如下:
      upstream www.xxx.com {
      # 需要負載的server列表,weight表示權重,weight默認為1,如果多個配置權重的節點,比較相對值
      server www.xxx.com:8080 weight=15;
      server www.xxx.com:9080 weight=10;
      }
  • ip hash
    • 優點:能實現同一個用戶始終訪問同一個服務器
    • 缺點:根據 ip hash 不一定平均
    • 配置示例如下:
      upstream www.xxx.com {
      ip_hash;
      # 需要負載的server列表
      server www.xxx.com:8080;
      server www.xxx.com:9080;
      }
  • url hash (第三方插件)
    • 優點:能實現同一個服務訪問同一個服務器,也就是根據url進行負載
    • 缺點:和ip hash一樣,根據 url hash 分配請求不一定平均,請求頻繁的url會請求到同一臺服務器上
    • 配置示例如下(需要事先安裝插件)
      upstream www.xxx.com {
      # 需要負載的server列表
      server www.xxx.com:8080;
      server www.xxx.com:9080;
      hash $request_uri;
      }
  • fair (第三方插件)
    • 特點:按後端服務器的響應時間來分配請求,響應時間短的優先分配
    • 配置示例如下(需要事先安裝插件)
      upstream www.xxx.com {
      # 需要負載的server列表
      server www.xxx.com:8080;
      server www.xxx.com:9080;
      fair;
      }

一些負載均衡參數簡介:

upstream www.xxx.com {
    ip_hash;
    # 需要負載的server列表
    server www.xxx.com:8080 down;  # down表示當前的server暫時不參與負載
    server www.xxx.com:9080 weight=2;  # weight默認值為1,weight的值越大,負載的權重就越大  
    server www.xxx.com:7080 backup;  # 其他所有的非backup機器,在down掉或者很忙的時候,才請求backup機器,也就是一個備用機器
    server www.xxx.com:6080;
}

Nginx+Tomcat搭建集群

在上文中我們已經介紹了如何在單機上部署多個Tomcat實例,本節將介紹如何安裝Nginx,並且使用Nginx+Tomcat搭建集群。

1.到nginx官網上獲取下載鏈接,然後到Linux上下載並解壓編譯nginx:

[root@study-01 ~]# cd /usr/local/src/
[root@study-01 /usr/local/src]# wget http://nginx.org/download/nginx-1.14.0.tar.gz
[root@study-01 /usr/local/src]# tar -zxvf nginx-1.14.0.tar.gz
[root@study-01 /usr/local/src]# cd nginx-1.14.0
[root@study-01 /usr/local/src/nginx-1.14.0]# ./configure --prefix=/usr/local/nginx
[root@study-01 /usr/local/src/nginx-1.14.0]# echo $?
0
[root@study-01 /usr/local/src/nginx-1.14.0]# make && make install
[root@study-01 /usr/local/src/nginx-1.14.0]# echo $?
0
[root@study-01 /usr/local/src/nginx-1.14.0]# cd ../../nginx/
[root@study-01 /usr/local/nginx]# ls  # 安裝完成
conf  html  logs  sbin
[root@study-01 /usr/local/nginx]#

2.創建nginx的主配置文件,因為我們不使用nginx自帶的配置文件:

[root@study-01 /usr/local/nginx/conf]# mv nginx.conf nginx.conf.bak
[root@study-01 /usr/local/nginx/conf]# vim nginx.conf  # 內容如下
user nobody nobody;
worker_processes 2;
error_log /usr/local/nginx/logs/nginx_error.log crit;
pid /usr/local/nginx/logs/nginx.pid;
worker_rlimit_nofile 51200;
events
{
    use epoll;
    worker_connections 6000;
}
http
{
    include mime.types;
    default_type application/octet-stream;
    server_names_hash_bucket_size 3526;
    server_names_hash_max_size 4096;
    log_format combined_realip ‘$remote_addr $http_x_forwarded_for [$time_local]‘
    ‘ $host "$request_uri" $status‘
    ‘ "$http_referer" "$http_user_agent"‘;
    sendfile on;
    tcp_nopush on;
    keepalive_timeout 30;
    client_header_timeout 3m;
    client_body_timeout 3m;
    send_timeout 3m;
    connection_pool_size 256;
    client_header_buffer_size 1k;
    large_client_header_buffers 8 4k;
    request_pool_size 4k;
    output_buffers 4 32k;
    postpone_output 1460;
    client_max_body_size 10m;
    client_body_buffer_size 256k;
    client_body_temp_path /usr/local/nginx/client_body_temp;
    proxy_temp_path /usr/local/nginx/proxy_temp;
    fastcgi_temp_path /usr/local/nginx/fastcgi_temp;
    fastcgi_intercept_errors on;
    tcp_nodelay on;
    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 8k;
    gzip_comp_level 5;
    gzip_http_version 1.1;
    gzip_types text/plain application/x-javascript text/css text/htm 
    application/xml;
    add_header Access-Control-Allow-Origin *;
    include vhost/*.conf;
}
[root@study-01 /usr/local/nginx/conf]# mkdir ./vhost  # 創建虛擬主機配置文件的存放目錄
[root@study-01 /usr/local/nginx/conf]# cd vhost/
[root@study-01 /usr/local/nginx/conf/vhost]# vim www.xxx.com.conf  # 創建虛擬主機配置文件,內容如下:
upstream 192.168.190.129 {
        # 需要負載的server列表,可以直接使用ip
        server 192.168.190.129:8080 weight=1;
        server 192.168.190.129:9080 weight=3;
        # server www.xxx.com:8080 weight=1;
        # server www.xxx.com:9080 weight=3;
}

server{
  listen 80;
  autoindex on;
  server_name 192.168.190;
  access_log /usr/local/nginx/logs/access.log combined;
  index index.html index.htm index.jsp;

  location / {
        proxy_pass http://192.168.190.129;
        add_header Access-Control-Allow-Origin *;
  }
}
[root@study-01 /usr/local/nginx/conf/vhost]# 

3.檢查nginx配置文件,顯示沒問題則啟動nginx服務:

[root@study-01 /usr/local/nginx/conf/vhost]# cd ../../sbin/
[root@study-01 /usr/local/nginx/sbin]# ./nginx -t  # 檢查nginx配置文件
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@study-01 /usr/local/nginx/sbin]# ./nginx -c /usr/local/nginx/conf/nginx.conf  # 啟動nginx服務
[root@study-01 /usr/local/nginx/sbin]# netstat -lntp | grep nginx  # 檢查端口是否已監聽
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      5676/nginx: master  
[root@study-01 /usr/local/nginx/sbin]# ps aux |grep nginx  # 檢查nginx進程是否正常
root       5676  0.0  0.0  20492   624 ?        Ss   19:57   0:00 nginx: master process ./nginx -c /usr/local/nginx/conf/nginx.conf
nobody     5677  0.0  0.0  22936  3220 ?        S    19:57   0:00 nginx: worker process
nobody     5678  0.0  0.0  22936  3220 ?        S    19:57   0:00 nginx: worker process
root       5683  0.0  0.0 112680   976 pts/0    S+   19:58   0:00 grep --color=auto nginx
[root@study-01 /usr/local/nginx/sbin]# 

4.啟動兩個Tomcat實例:

[root@study-01 ~]# cd /usr/local/tomcat9-01/bin/
[root@study-01 /usr/local/tomcat9-01/bin]# ./startup.sh 
Using CATALINA_BASE:   /usr/local/tomcat9-01
Using CATALINA_HOME:   /usr/local/tomcat9-01
Using CATALINA_TMPDIR: /usr/local/tomcat9-01/temp
Using JRE_HOME:        /usr/local/jdk1.8
Using CLASSPATH:       /usr/local/tomcat9-01/bin/bootstrap.jar:/usr/local/tomcat9-01/bin/tomcat-juli.jar
Tomcat started.
[root@study-01 /usr/local/tomcat9-01/bin]# cd /usr/local/tomcat9-02/bin/
[root@study-01 /usr/local/tomcat9-02/bin]# ./startup.sh 
Using CATALINA_BASE:   /usr/local/tomcat9-02
Using CATALINA_HOME:   /usr/local/tomcat9-02
Using CATALINA_TMPDIR: /usr/local/tomcat9-02/temp
Using JRE_HOME:        /usr/local/jdk1.8
Using CLASSPATH:       /usr/local/tomcat9-02/bin/bootstrap.jar:/usr/local/tomcat9-02/bin/tomcat-juli.jar
Tomcat started.
[root@study-01 /usr/local/tomcat9-02/bin]# 

5.修改第二個Tomcat實例index.jsp文件內容,以作為兩個Tomcat實例的區別,方便一會驗證負載均衡是否已成功生效:

[root@study-01 ~]# vim /usr/local/tomcat9-02/webapps/ROOT/index.jsp 
<div id="congrats" class="curved container">
    <h2>I‘m Tomcat 2</h2>
</div>
[root@study-01 ~]# 

6.設置防火墻規則,開放80端口:

[root@study-01 ~]# firewall-cmd --zone=public --add-port=80/tcp --permanent
success
[root@study-01 ~]# firewall-cmd --reload
success
[root@study-01 ~]# 

7.使用瀏覽器進行訪問,驗證nginx的負載均衡是否已成功生效:
技術分享圖片
技術分享圖片

如上,驗證成功,我們配置的nginx的負載均衡成功。到此為止,我們的Tomcat集群環境就搭建完成了。

Nginx+Tomcat搭建集群環境