前言
本文主要介紹如何在 CentOS 上從零開始使用 Nginx + Tomcat 搭建一個負載均衡伺服器。在搭建過程中學習 Nginx 的基本使用方式以及 Tomcat 相關知識,進一步理解兩者結合後的執行原理。
Nginx 安裝
使用原始碼編譯的方式在 CentOS 上安裝 Nginx 主要有以下幾個步驟:
-
安裝執行環境
- Nginx 是使用 C 語言開發的,編譯依賴 gcc 環境,因此如果沒有 gcc 需要先安裝:
yum install -y gcc-c++ 複製程式碼
- 安裝 Nginx 依賴庫
# rewrite模組需要 PCRE(Perl Compatible Regular Expressions),pcre-devel 庫 yum install -y pcre pcre-devel # gzip模組需要 zlib 庫 yum install -y zlib # ssl 功能需要 OpenSSL 庫 yum install -y openssl openssl-devel 複製程式碼
-
下載 Ngnix
# 如果還未安裝 wget 請先執行安裝命令 yum install -y wget # 使用 wget 命令下載 wget -c https://nginx.org/download/nginx-1.12.2.tar.gz # 解壓檔案 tar -zxvf nginx-1.12.2.tar.gz # 進入解壓後的目錄 cd nginx-1.12.2 # 使用預設配置 ./configure 複製程式碼
-
編譯安裝 Nginx
編譯安裝十分簡單,只需執行兩個命令即可
# 編譯 make # 安裝 make install # 安裝目錄預設為 /usr/local/nginx # 可以使用 whereis nginx 查詢 [root@localhost nginx-1.12.2]# whereis nginx nginx: /usr/local/nginx 複製程式碼
-
啟動測試
Ngnix 安裝完成後即可啟動測試是否可以正常執行
# 進入 ngnix 執行檔案目錄 cd /usr/local/ngnix/sbin # 啟動 # ./nginx 啟動 # ./nginx -s stop 停止(先查出 nginx 程式 id 再使用 kill 命令強制殺掉程式) # ./nginx -s quit 退出(等待 nginx 程式將任務處理完畢再停止) # ./nginx -s reload 重新載入,適用於修改了配置檔案之後操作 ./nginx # 啟動之後可以通過 ps 命令查詢 ngnix 程式 ps aux|grep nginx # 訪問localhost:80 測試 ngnix 是否正常執行,返回 nginx 歡迎頁表示正常執行 [root@localhost sbin]# curl localhost:80 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> 複製程式碼
Tomcat 多例項部署配置
Tomcat 單例項部署,即一個 Tomcat 伺服器執行時,不存在負載均衡一說,因此,我們首先要做的就是實現 Tomcat 多例項部署,將我們的同一個應用程式部署在多個 Tomcat 伺服器上同時執行。主要步驟如下:
- 安裝 JDK(如果本機已經安裝了則跳過第一步)
# 下載、解壓 JDK8,下載地址可以從官網獲取
wget http://download.oracle.com/otn-pub/java/jdk/8u161-b12/2f38c3b165be4555a1fa6e98c45e0808/jdk-8u161-linux-x64.tar.gz?AuthParam=1520068673_6f545cf32470b83658219011266e65b8
# 配置 Java 環境變數
vi /etc/profile
# 在檔案尾部新增以下內容
export JAVA_HOME=/usr/local/jdk1.8.0_161 (這裡是JDK所在目錄)
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
# 儲存完成後重新載入 /etc/profile 檔案
source /etc/profile
# 測試是否配置正確
[root@localhost local]# java -version
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
複製程式碼
- 下載 Tomcat
# 下載 Tomcat 9
wget http://mirrors.hust.edu.cn/apache/tomcat/tomcat-9/v9.0.5/bin/apache-tomcat-9.0.5.tar.gz
# 解壓
tar -zxvf apache-tomcat-9.0.5.tar.gz
# 為接下來的步驟做準備
# 重新命名為tomcat-home
mv apache-tomcat-9.0.5 tomcat-home
# 複製第二份,重新命名為tomcat-8080
cp -R tomcat-home tomcat-8080
# 複製第三份,重新命名為tomcat-9090
cp -R tomcat-home tomcat-9090
複製程式碼
-
分離目錄
首先介紹兩個 tomcat 中比較重要的概念(通常也是兩個系統變數)CATALINA_HOME 和 CATALINA_BASE
- CATALINA_HOME:即指向Tomcat安裝路徑的系統變數(安裝目錄)
- CATALINA_BASE:即指向活躍配置路徑的系統變數(工作目錄)
通過設定這兩個變數,就可以將tomcat的安裝目錄和工作目錄分離,從而實現tomcat多例項的部署。 下面就是 Tomcat 的基本目錄結構,以及對應的作用。
目錄 簡介 bin 存放指令碼檔案,例如比較常用的啟動和關閉指令碼 startup.sh、shutdown.sh 等 conf 存放配置檔案,最重要的是 server.xml,它是 tomcat 的主要配置檔案 lib Tomcat 執行需要的依賴包 log 存放日誌檔案 temp 存放執行時產生的臨時檔案 webapps web 應用的預設目錄 work 主要存放由JSP檔案生成的servlet(java檔案以及最終編譯生成的class檔案) Tomcat 官方文件 說明了 CATALINA_HOME 路徑下需要包含 bin 和 lib 目錄,也就是兩個支援 tomcat 執行的目錄,而 CATALINA_BASE 可以包含所有目錄,但是 bin 和 lib 不是必須的,預設時會使用 CATALINA_HOME 中的 bin 和 lib。因此我們就可以使用一個 CATALINA_HOME 和多個 CATALINA_BASE 部署多個例項,這樣的好處是便於管理和升級 Tomcat。上一步我們已經複製了三個 Tomcat,它們的作用分別是:
目錄 作用 tomcat-home 作為 CATALINA_HOME,即只需要保留 bin 和 lib 兩個資料夾 tomcat-8080 作為 CATALINA_BASE,需要保留除了 bin 和 lib 之外的其他資料夾,使用 8080 埠 tomcat-9090 同 tomcat-8080,使用 9090 埠 基於 CATALINA_HOME 和 CATALINA_BASE 分離目錄
# 根據上面表格整理完目錄之後,目錄結構如下: [root@localhost tomcat-home]# ls bin lib LICENSE NOTICE RELEASE-NOTES RUNNING.txt [root@localhost tomcat-8080]# ls conf LICENSE logs NOTICE RELEASE-NOTES RUNNING.txt temp webapps work [root@localhost tomcat-9090]# ls conf LICENSE logs NOTICE RELEASE-NOTES RUNNING.txt temp webapps work 複製程式碼
-
修改 Tomcat 配置檔案
這一步主要是修改 server.xml 中埠的配置,在 server.xml 中配置了四個監聽埠,分別是:
- Server port(預設8005): 監聽關閉 tomcat 的 shutdown 命令
- Connector port(預設8080):監聽 http 請求
- AJP Connector port(預設8009):監聽 AJP 請求
- redirectPort(預設8443):重定向埠,出現在Connector配置中,如果該Connector僅支援非SSL的普通http請求,那麼該埠會把https的請求轉發到這個Redirect Port指定的埠。
瞭解了監聽的各個埠的作用之後就可以開始修改 server.xml 了,如果不使用 AJP 請求,那麼我們只需要保證多例項中的 Server port 和 Connector port 不同即可。
# tomcat-8080 保持預設配置即可 # 修改 tomcat-9090 的配置,修改後的 /usr/local/tomcat-9090/conf/server.xml 內容如下: ... <Server port="9005" shutdown="SHUTDOWN"> ... <Connector port="9090" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> ... 複製程式碼
-
編寫指令碼
前面的準備工作做完之後就可以啟動 tomcat 了,但是現在只有 tomcat-home/bin 目錄下有 startup.sh 和 shutdown.sh,而我們要啟動的 8080 和 9090 兩個例項,因此我們就需要編寫一段指令碼,修改 CATALINA_BASE 來達到分別操作兩個例項的目的。
-
啟動指令碼 start.sh:
#!/bin/sh CUR_DIR=`dirname $BASH_SOURCE` export CATALINA_BASE=`readlink -f $CUR_DIR` export CATALINA_HOME="/usr/local/tomcat-home" if [ -f $CATALINA_HOME/bin/startup.sh ]; then $CATALINA_HOME/bin/startup.sh else echo "$CATALINA_HOME/bin/startup.sh not exist" fi 複製程式碼
-
停止指令碼 stop.sh:
#!/bin/sh CUR_DIR=`dirname $BASH_SOURCE` export CATALINA_BASE=`readlink -f $CUR_DIR` export CATALINA_HOME="/usr/local/tomcat-home" if [ -f $CATALINA_HOME/bin/shutdown.sh ]; then $CATALINA_HOME/bin/shutdown.sh else echo "$CATALINA_HOME/bin/shutdown.sh not exist" fi 複製程式碼
將這兩個指令碼檔案放在 tomcat-8080 和 tomcat-9090 的根目錄下即可
[root@localhost tomcat-8080]# ls conf logs RELEASE-NOTES start.sh temp work LICENSE NOTICE RUNNING.txt stop.sh webapps # 啟動 8080 埠的 tomcat [root@localhost tomcat-8080]# ./start.sh Using CATALINA_BASE: /usr/local/tomcat-8080 Using CATALINA_HOME: /usr/local/tomcat-home Using CATALINA_TMPDIR: /usr/local/tomcat-8080/temp Using JRE_HOME: /usr/local/jdk1.8.0_161 Using CLASSPATH: /usr/local/tomcat-home/bin/bootstrap.jar:/usr/local/tomcat-home/bin/tomcat-juli.jar Tomcat started. # 停止 [root@localhost tomcat-8080]# ./stop.sh Using CATALINA_BASE: /usr/local/tomcat-8080 Using CATALINA_HOME: /usr/local/tomcat-home Using CATALINA_TMPDIR: /usr/local/tomcat-8080/temp Using JRE_HOME: /usr/local/jdk1.8.0_161 Using CLASSPATH: /usr/local/tomcat-home/bin/bootstrap.jar:/usr/local/tomcat-home/bin/tomcat-juli.jar 複製程式碼
-
測試兩個 Tomcat 是否同時正常執行
為了方便測試,在 /usr/local/tomcat-8080/webapps/ROOT 和 /usr/local/tomcat-9090/webapps/ROOT 目錄下分別新建一個 index.html 檔案,內容分別為 "tomcat-8080" 和 "tomcat-9090" 便於我們區分。完成之後使用 start.sh 啟動兩個例項,這裡我們同樣使用 curl 訪問來測試。
# 訪問 9090 埠,獲取到 9090 的資料 [root@localhost tomcat-9090]# curl localhost:9090 <h1> tomcat-9090 </h1> # 訪問 8080 埠,獲取到 8080 的資料 [root@localhost tomcat-8080]# curl localhost:8080 <h1> tomcat-8080 </h1> 複製程式碼
Nginx 與 Tomcat 結合
Ngnix 和 Tomcat 結合實現負載均衡的需求大概是這樣的:使用者訪問伺服器的 8888 埠,Ngnix 接收到請求之後轉發至 8080 埠或者 9090 埠由 Tomcat 處理。兩個 Tomcat 部署了同一個應用,這樣就可以實現負載均衡,可以由兩個 Tomcat 同時處理使用者請求。這裡我們以 localhost 為例,開始配置 Ngnix
這裡使用 localhost 作為示例,正式使用時在配置檔案中使用域名替換 localhost 即可
# 進入 ngnix 配置檔案的目錄
# 預設配置檔案是 ngnix.conf
/usr/local/nginx/conf
# 這裡我們新建一個 localhost.conf 單獨配置,內容如下:
upstream localhost {
server 127.0.0.1:8080;
server 127.0.0.1:9090;
}
server
{
listen 8888;
server_name localhost;
index index.html index.htm index.jsp index.php;
location / {
proxy_pass http://localhost;
proxy_set_header X-Real-IP $remote_addr;
add_header X-Slave $upstream_addr;
}
}
# 接著將在 nginx.conf 中引入 localhost.conf
...
http {
...
# 引入 localhost.conf;
include /usr/local/nginx/conf/localhost.conf;
...
}
...
# 完成配置檔案修改之後可以通過 ./nginx -t 命令測試配置檔案是否正確
cd /usr/local/nginx/sbin/
./nginx -t
# 出現下面提示表示配置正確,如果有誤的話檢查配置檔案
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
# 過載 ngnix 配置檔案
./nginx -s reload
複製程式碼
至此,Nginx + Tomcat 的負責均衡伺服器已經搭建完成,現在訪問 localhost:8888 就可以看到兩個 Tomcat 都能處理來自 8888 埠的請求了
[root@localhost sbin]# curl localhost:8888
<h1> tomcat-8080 </h1>
[root@localhost sbin]# curl localhost:8888
<h1> tomcat-9090 </h1>
複製程式碼
負載均衡策略
上面我們使用的是 Nginx 預設的負載均衡策略,我們也可以根據自己需求配置其他的策略,Nginx 提供的策略主要有以下幾種:
-
輪詢(預設)
每個請求按時間順序逐一分配到不同的後端伺服器,如果後端伺服器掛掉,能自動忽略該伺服器。
upstream localhost { server 127.0.0.1:8080; server 127.0.0.1:9090; } 複製程式碼
-
權重
根據配置的權重去分配給不同的伺服器處理,適用於伺服器效能有差距的情況,可以個高效能的伺服器分配高權重
upstream localhost { server 127.0.0.1:8080 weight=1; server 127.0.0.1:9090 weight=3; } 複製程式碼
-
IP 繫結 ip_hash
每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端伺服器,可以解決 session 的問題。
upstream localhost { ip_hash; server 127.0.0.1:8080; server 127.0.0.1:9090; } 複製程式碼
-
最少連線
將請求分配給當前連線數最少的伺服器
upstream localhost { least_conn; server 127.0.0.1:8080; server 127.0.0.1:9090; } 複製程式碼
總結
以上,在 CentOS 上使用 Nginx + Tomcat 搭建負載均衡伺服器已經完成,搭建過程中主要是理解如何利用 CATALINA_HOME 和 CATALINA_BASE 實現 Tomcat 的多例項部署,在完成 Tomcat 多例項部署的基礎上結合 Nginx 實現負載均衡就很簡單了。