文章目錄
- 前言
- 一、反向代理
- 1.1 反向代理原理
- 1.2 實驗配置示例
- 二、負載均衡
- 2.1 負載均衡基本原理
- 2.2 常見負載均衡策略
- 2.2.1 輪詢(Round Robin)(最常用)
- 2.2.2 最少連接數(Least Connections)
- 2.2.3 IP 哈希(IP Hash)
- 2.2.4 加權輪詢(Weighted Round Robin)
- 2.2.5 最少時間算法(Least Time)
- 2.2.6 一致性哈希(Consistent Hashing)
- 2.3 配置示例
- 2.3.1 基礎輪詢配置
- 2.3.2 帶權重和故障轉移的配置
- 2.4 高可用與健康檢查
- 2.5 負載均衡總結
- 三、Tomcat 后端服務器
- 3.1 Tomcat 概述
- 3.2 運行原理
- 3.3 主要配置文件
- 3.4 調用應用接口
- 3.5 調用數據庫接口
- 3.6 Tomcat 部署步驟
- 3.6.1 環境準備
- 3.6.2 JDK 安裝與環境變量配置
- 3.6.3 安裝與啟動 Tomcat
- 3.7 Tomcat總結
- 四、Nginx + Tomcat 實戰:反向代理與負載均衡
- 4.1 環境規劃
- 4.2 Nginx 負載均衡器部署
- 4.3 Tomcat 應用服務器部署
- 4.4 動靜分離配置
- 4.4.1 Tomcat1 配置
- 4.4.2 Tomcat2 配置
- 4.4.3 Nginx 配置
- 4.5 效果測試
- 總結
前言
在現代 Web 架構中,Nginx 作為高性能的反向代理和負載均衡服務器,被廣泛應用于生產環境中。它不僅可以有效提升系統的并發處理能力、可用性和擴展性,還能實現動靜分離、請求分發等關鍵功能。本文將從原理到實踐,系統介紹 Nginx 的反向代理與負載均衡機制,并結合 Tomcat 后端服務器的部署與配置,提供一個完整的實戰指南。
一、反向代理
1.1 反向代理原理
反向代理是Nginx的核心功能之一,其工作原理如下:
- 用戶請求首先到達 Nginx 服務器
- Nginx根據配置將請求轉發給后端應用服務器/業務服務器(如Tomcat、Node.js、Spring Boot等)
- 后端:php python java(java后端 、tomcat 、微服務)
- Nginx 在這一過程中充當“中轉站”的角色,客戶端并不知道真正提供服務的后端服務器是哪一臺,從而實現了請求的轉發與隱藏后端服務器的作用
基本流程如下:
客戶端 → Nginx → 后端服務器集群
1.2 實驗配置示例
要配置 Nginx 作為反向代理,需編輯 nginx.conf
文件,在 server
塊中添加如下配置:
server {listen 80;server_name localhost;location / {proxy_pass http://127.0.0.1(后端IP):8080; # 將請求轉發至后端8080端口==========================================================proxy_set_header Host $host; # 保留原始 Host 頭信息proxy_set_header X-Real-IP $remote_addr; # 傳遞客戶端真實 IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;==========================================================}
}
保存配置后,執行以下命令重新加載 Nginx:
nginx -s reload
或者
systemctl reload nginx
此時訪問 http://localhost/
,實際請求將由 Nginx 轉發至 http://127.0.0.1:8080/
。
二、負載均衡
2.1 負載均衡基本原理
負載均衡(Load Balancing)是 Nginx 的核心功能之一,通過將客戶端請求分發到多臺后端服務器,顯著提升系統的并發處理能力、可用性和穩定性。
主要優勢包括:
- 提升性能:分散單臺服務器壓力;
- 高可用性:某臺服務器故障時,自動將請求轉發至其他正常節點;
- 良好的擴展性:可靈活增刪后端服務器節點。
2.2 常見負載均衡策略
Nginx 支持多種負載均衡算法,可根據實際業務場景選擇合適的策略。
2.2.1 輪詢(Round Robin)(最常用)
輪詢算法是 Nginx 的默認分流算法。它按順序將請求依次分配給每一臺后端服務器,直到最后一臺服務器,然后重新從第一臺服務器開始。這種方法簡單且均勻地分配了流量。
數據流向:每個請求依次被分配到下一個服務器。假設有三臺服務器(Server A、Server B、Server C),第一個請求被分配到 Server A,第二個請求分配到 Server B,第三個請求分配到 Server C,第四個請求又回到 Server A,依此類推。
?特點??:
- Nginx默認的負載均衡算法
- 請求按順序均勻分配到每臺后端服務器,無視服務器的當前負載和響應時間
- 簡單高效,適合服務器性能相近的場景
配置示例:
upstream backend {server backend1.example.com;server backend2.example.com;server backend3.example.com;
}
2.2.2 最少連接數(Least Connections)
最少連接數算法將請求分配給當前活動連接數最少的服務器。這種算法適用于請求處理時間不均勻的情況,可以有效平衡服務器的負載。
數據流向:每個請求被分配到當前連接數最少的服務器。例如,Server A 有 2 個連接,Server B 有 5 個連接,新的請求會被分配到 Server A。
特點??:
- 將請求分配給當前活動連接數最少的服務器
- 動態均衡負載,適用于請求處理時間不一的場景
- 有效避免服務器過載
配置示例:
upstream backend {least_conn;server backend1.example.com;server backend2.example.com;server backend3.example.com;
}
2.2.3 IP 哈希(IP Hash)
IP 哈希算法通過計算客戶端 IP 地址的哈希值,將請求始終分配給同一臺服務器。適用于需要將特定客戶端的請求固定在同一臺服務器上的場景。
數據流向:每個客戶端的 IP 地址被哈希計算,然后根據哈希值將請求固定分配到某一臺服務器。假設客戶端 X 的哈希值指向 Server A,客戶端 Y 的哈希值指向 Server B,則無論多少次請求,X 的請求總是流向 Server A,Y 的請求總是流向 Server B。
特點??:
- 基于客戶端IP地址計算哈希值
- 同一個客戶端總是被分配到同一臺服務器,有助于會話保持
配置示例:
upstream backend {ip_hash;server backend1.example.com;server backend2.example.com;server backend3.example.com;
}
2.2.4 加權輪詢(Weighted Round Robin)
加權輪詢算法允許為每臺服務器設置權重,權重越大的服務器將會獲得更多的請求。適用于服務器性能不均衡的情況。
數據流向:根據服務器設置的權重值分配請求。假設 Server A 權重為 3,Server B 權重為 1,則 4 個請求中,3 個會被分配到 Server A,1 個會被分配到 Server B。
?特點??:
- 允許為每臺服務器設置權重值
- 權重越高的服務器獲得更多請求
- 適合服務器性能不均衡的環境
配置示例:
upstream backend {server backend1.example.com weight=3;server backend2.example.com weight=1;server backend3.example.com weight=2;
}
2.2.5 最少時間算法(Least Time)
最少時間算法基于請求的響應時間,將請求分配給響應時間最短的服務器。這種算法在 Nginx 1.15.3 及以后版本中可用,適用于需要最大化響應速度的場景。
數據流向:每個請求分配到響應時間最短或平均連接時間最短的服務器。假設 Server A 的響應時間較快,Server B 較慢,則新的請求更可能流向 Server A。
特點??:
- 基于服務器響應時間進行智能分配
- 將請求分配給響應時間最短的服務器,適用于對響應速度要求較高的場景
- Nginx 1.15.3及以上版本支持
- 進一步優化了最少連接算法,適用于高負載環境下的動態負載均衡
配置示例:
upstream backend {least_time header;server backend1.example.com;server backend2.example.com;server backend3.example.com;
}
2.2.6 一致性哈希(Consistent Hashing)
一致性哈希將服務器和請求的鍵(如URL)映射到一個??哈希環??上,當集群中某臺服務器故障時,只有部分請求會重新分配到其他服務器,而不是全部重新分配(IP哈希會全部分配,因為它是計算出哈希值后取余)。這在緩存等場景中非常有用。
數據流向:根據請求的某個特定參數(如 URL、Cookie 或其他 Header),進行哈希計算,將請求分配到哈希值對應的服務器。假設 Server A 和 Server B,參數 “foo” 的哈希值指向 Server A,參數 “bar” 的哈希值指向 Server B,則 “foo” 請求總是流向 Server A,“bar” 請求總是流向 Server B。
特點??:
- 基于特定參數(如URL)計算哈希值,服務器節點變動時僅影響部分請求
- 適應服務器節點變動,減少請求的重新分配,適合緩存敏感的場景
- 需要第三方模塊支持
配置示例:(需要第三方模塊如ngx_http_upstream_hash_module
)
upstream backend {hash $request_uri consistent;server backend1.example.com;server backend2.example.com;server backend3.example.com;
}
2.3 配置示例
2.3.1 基礎輪詢配置
http {upstream backend {server 192.168.0.101;server 192.168.0.102;}server {listen 80;location / {proxy_pass http://backend;}}
}
2.3.2 帶權重和故障轉移的配置
upstream backend {server 192.168.0.101 weight=3 max_fails=3 fail_timeout=30s;server 192.168.0.102 weight=1 max_fails=3 fail_timeout=30s;
}
max_fails
表示允許失敗的次數,fail_timeout
表示失敗后暫停轉發的時間。
2.4 高可用與健康檢查
Nginx 開源版自帶被動健康檢查,僅在請求失敗時標記服務器不可用。如需主動健康檢查(定時探測后端狀態),可選用:
- Nginx Plus 版本;
- 第三方模塊如
nginx_upstream_check_module
。
2.5 負載均衡總結
Nginx 負載均衡就是通過反向代理把客戶端請求按策略分配到多臺后端服務器,實現高性能、高可用、可擴展的服務訪問。
三、Tomcat 后端服務器
3.1 Tomcat 概述
Tomcat 是一個輕量級的 Web 應用服務器(Web Server + Servlet Container),也是一個 Servlet 容器,主要用于托管基于 Servlet、JSP、Spring MVC 等技術的 Java Web 應用。
主要功能包括:
- 接收 HTTP 請求(內置了一個簡單的 HTTP 服務器)
- 將請求分發給對應的 Web 應用(基于 URL 映射)
- 執行 Servlet / JSP 并生成響應
- 返回 HTTP 響應給客戶端
換句話說,Tomcat 是一個 Java Web 應用運行環境,可以托管基于 Servlet、JSP、Spring MVC、Spring Boot(war 部署)等的應用。
3.2 運行原理
1、請求入口與代理??
- 用戶通過瀏覽器發起請求(如訪問網站),首先由??Nginx服務器??(監聽80端口)接收。
- Nginx作為反向代理,將請求轉發至Tomcat的??8080端口??(Tomcat默認服務端口)。
2、Web容器處理請求??
- Tomcat的??Web容器??接收轉發后的請求,解析請求類型(例如識別到需要處理index.jsp動態頁面)。
- 容器根據URL映射確定對應的Web應用資源。
3、JSP到Servlet的轉換??
- ??JSP容器??將index.jsp文件中的Java代碼(如<% … %>標簽)翻譯成完整的??Servlet代碼??(本質是一個Java類)。
- 此步驟會生成Servlet的.java文件,并編譯為.class字節碼文件(僅首次請求或修改時觸發)。
4、??Servlet執行與業務邏輯??
- ??Servlet容器??(如Tomcat中的Catalina)加載并執行編譯后的Servlet。
- Servlet處理業務邏輯,可能包含:
- 調用API接口??(如與淘寶/京東等第三方服務交互);
- 連接MySQL數據庫??(執行查詢或更新操作);
- 生成動態內容(如HTML響應)。
5、響應返回客戶端??
- Servlet將處理結果返回給Web容器,容器封裝為HTTP響應。
- 響應通過Nginx原路返回至用戶瀏覽器,完成整個流程。
3.3 主要配置文件
Tomcat 的核心配置文件主要有:
文件 | 作用 |
---|---|
conf/server.xml | Tomcat 的主配置文件,定義 Connector (端口、協議)、Engine 、Host 、Context 等 |
conf/web.xml | 全局的 Web 應用默認配置(比如默認的 MIME 映射、默認 Servlet) |
context.xml | 定義 Web 應用級別的配置,如數據源(JNDI)、Session 配置 |
tomcat-users.xml | 用戶、角色和安全相關配置,用于 Manager App、Admin Console 登錄 |
應用內的 WEB-INF/web.xml | 每個 Web 應用自己的 Servlet、Filter、Listener 配置 |
3.4 調用應用接口
應用接口:Tomcat 負責將請求轉交給指定的 Servlet 或框架(如 Spring MVC);
當你的應用部署到 Tomcat 中時,Tomcat 會:
- 在啟動時加載你的
web.xml
或注解(如@WebServlet
) - 創建并初始化 Servlet
- 當有 HTTP 請求時,將請求參數封裝成
HttpServletRequest
- 調用你的 Servlet 或框架(如 Spring MVC 的 DispatcherServlet)
- 你的業務代碼處理完成后返回
HttpServletResponse
也就是說,Tomcat 并不關心業務邏輯,只負責把請求轉給你的代碼執行。
3.5 調用數據庫接口
數據庫接口:可通過 JNDI 數據源實現數據庫連接池的配置與管理,提升性能與可維護性。
Tomcat 提供了 JNDI 數據源 支持,讓應用能復用數據庫連接池:
-
配置數據源
在context.xml
或某個應用的META-INF/context.xml
:<Resource name="jdbc/MyDB" auth="Container"type="javax.sql.DataSource"maxActive="20"maxIdle="10"maxWait="10000"username="root"password="123456"driverClassName="com.mysql.cj.jdbc.Driver"url="jdbc:mysql://localhost:3306/test"/>
-
應用代碼獲取數據源
Context initCtx = new InitialContext(); DataSource ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/MyDB"); Connection conn = ds.getConnection(); // 執行 SQL ...
這樣做的好處:
- 連接池由 Tomcat 管理,性能更好
- 數據源配置與應用解耦,方便運維
3.6 Tomcat 部署步驟
3.6.1 環境準備
關閉防火墻 與增強功能
systemctl stop firewalld
setenforce 0
3.6.2 JDK 安裝與環境變量配置
# 配置JDK,現在系統基本自帶openJDK
tar zxvf jdk-8u91-linux-x64.tar.gz -C /usr/local/
vim /etc/profile
添加以下內容:
export JAVA_HOME=/usr/local/jdk1.8.0_91 #指定JDK安裝目錄
export JRE_HOME=${JAVA_HOME}/jre #指定JDK目錄中的JRE
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib #包含當前目錄和JAVA庫目錄
export PATH=${JAVA_HOME}/bin:$PATH #將JDK bin目錄添加到PATH,使得JAVA相關命令可以全局執行
執行 source /etc/profile
使配置生效。
# 使配置生效
source /etc/profile# 驗證安裝
java -version
3.6.3 安裝與啟動 Tomcat
#先下載安裝包,然后再解壓
tar zxvf apache-tomcat-8.5.35.tar.gz
#修改服務名字
mv apache-tomcat-8.5.35 /usr/local/tomcat
# 啟動/停止命令
/usr/local/tomcat/bin/startup.sh # 啟動
/usr/local/tomcat/bin/shutdown.sh # 關閉
# 驗證端口
netstat -ntap | grep 8080
# 查看進程
ps -aux|grep java
3.7 Tomcat總結
- 本質:Tomcat 是 Java Web 應用的運行容器,負責接收 HTTP 請求、調用 Servlet、返回響應
- 原理:Connector 監聽請求 → Mapper 分發 → Servlet 執行 → 返回響應
- 配置文件:server.xml(端口、Host)、web.xml(全局)、context.xml(數據源)、tomcat-users.xml(用戶)
- 應用接口調用:Tomcat 把請求交給你的 Servlet/框架
- 數據庫接口調用:通過 JNDI 數據源或自己管理 JDBC 連接
四、Nginx + Tomcat 實戰:反向代理與負載均衡
4.1 環境規劃
- Nginx 負載均衡器:192.168.10.110:80
- Tomcat 服務器1:192.168.10.123:8080
- Tomcat 服務器2:192.168.10.123:8081
4.2 Nginx 負載均衡器部署
如已安裝可跳過,否則執行:
# 安裝依賴與編譯安裝
yum -y install pcre-devel zlib-devel openssl-devel gcc gcc-c++ make
useradd -M -s /sbin/nologin nginx
cd /opt
tar zxvf nginx-1.20.2.tar.gz -C /opt/
cd nginx-1.20.2/
./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-file-aio \ #啟用文件修改支持
--with-http_stub_status_module \ #啟用狀態統計
--with-http_gzip_static_module \ #啟用 gzip靜態壓縮
--with-http_flv_module \ #啟用 flv模塊,提供對 flv 視頻的偽流支持
--with-http_ssl_module #啟用 SSL模塊,提供SSL加密功能
--with-stream #啟用 stream模塊,提供4層調度----------------------------------------------------------------------------------------------------------
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-file-aio --with-http_stub_status_module --with-http_gzip_static_module --with-http_flv_module --with-stream --with-http_ssl_modulemake && make install# 創建系統服務
vim /lib/systemd/system/nginx.service
[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx
ExecrReload=/bin/kill -s HUP $MAINPID
ExecrStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.targetchmod 754 /lib/systemd/system/nginx.service
# 添加服務配置內容
systemctl start nginx
systemctl enable nginx
4.3 Tomcat 應用服務器部署
systemctl stop firewalld
setenforce 0tar zxvf jdk-8u91-linux-x64.tar.gz -C /usr/local/vim /etc/profile
export JAVA_HOME=/usr/local1/jdk1.8.0_91
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATHsource /etc/profile
==============================================================
tar zxvf apache-tomcat-8.5.35.tar.gzmv /opt/apache-tomcat-8.5.35/ /usr/local/tomcat/usr/local/tomcat/bin/shutdown.sh
/usr/local/tomcat/bin/startup.shnetstat -ntap | grep 8080第二臺直接拷貝即可
cp -r /usr/local/tomcat /usr/local/tomcat1
4.4 動靜分離配置
4.4.1 Tomcat1 配置
cd /usr/local/tomcat/webapps/ROOT/
mv index.jsp index.jsp.bak # 備份默認的index.jsp
vim index.jsp<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP test1 page</title> #指定為 test1 頁面
</head>
<body>
<% out.println("動態頁面 1,http://www.test1.com");%>
</body>
</html># 重啟Tomcat
/usr/local/tomcat/bin/shutdown.sh
/usr/local/tomcat/bin/startup.sh
也可以這么配置:
mkdir /usr/local/tomcat/webapps/test
vim /usr/local/tomcat/webapps/test/index.jsp<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP test1 page</title> #指定為 test1 頁面
</head>
<body>
<% out.println("動態頁面 1,http://www.test1.com");%>
</body>
</html>vim /usr/local/tomcat/conf/server.xml
#由于主機名 name 配置都為 localhost,需要刪除前面的 HOST 配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false"><Context docBase="/usr/local/tomcat/webapps/test" path="" reloadable="true"></Context>
</Host>
4.4.2 Tomcat2 配置
cd /usr/local/tomcat1/webapps/ROOT/
mv index.jsp index.jsp.bak # 備份默認的index.jsp
vim index.jsp<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>JSP test2 page</title> #指定為 test2 頁面
</head>
<body>
<% out.println("動態頁面 2,http://www.test2.com");%>
</body>
</html># 修改server.xml
vim /usr/local/tomcat/tomcat1/conf/server.xml
22 <Server port="8006" shutdown="SHUTDOWN"> # 8005 換成8006
69 <Connector port="8081" protocol="HTTP/1.1" # 8080 改成8081
116 <Connector port="8010" protocol="AJP/1.3" redirectPort="8443" /> # 把8009 改成8010
# 重啟Tomcat
/usr/local/tomcat/tomcat1/bin/shutdown.sh
/usr/local/tomcat/tomcat1/bin/startup.sh
4.4.3 Nginx 配置
#準備靜態頁面和靜態圖片
echo '<html><body><h1>這是靜態頁面</h1></body></html>' > /usr/local/nginx/html/index.html
cp /root/game.jpg /usr/local/nginx/html/img
# 修改nginx配置文件
vim /usr/local/nginx/conf/nginx.conf
......
http {
......#gzip on;#配置負載均衡的服務器列表,weight參數表示權重,權重越高,被分配到的概率越大upstream tomcat_server {server 192.168.10.123:8080 weight=1;server 192.168.10.123:8081 weight=1;}server {listen 80;server_name www.yjs.com;charset utf-8;#access_log logs/host.access.log main;location / {root html;index index.html index.htm;}#配置Nginx處理動態頁面請求,將 .jsp文件請求轉發到Tomcat 服務器處理location ~ .*\.jsp$ {proxy_pass http://tomcat_server;#設置后端的Web服務器可以獲取遠程客戶端的真實IP##設定后端的Web服務器接收到的請求訪問的主機名(域名或IP、端口),默認HOST的值為proxy_pass指令設置的主機名。如果反向代理服務器不重寫該請求頭的話,那么后端真實服務器在處理時會認為所有的請求都來在反向代理服務器,如果后端有防攻擊策略的話,那么機器就被封掉了。proxy_set_header HOST $host; ##把$remote_addr賦值給X-Real-IP,來獲取源IPproxy_set_header X-Real-IP $remote_addr;##在nginx 作為代理服務器時,設置的IP列表,會把經過的機器ip,代理機器ip都記錄下來proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}#配置Nginx處理靜態圖片請求location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css)$ {root /usr/local/nginx/html/img;# ??緩存 10 天expires 10d;}
......}
......
}# 加載配置文件
systemctl reload nginx
4.5 效果測試
1、測試靜態頁面效果
- 靜態頁面訪問:
http://192.168.10.110/
- 瀏覽器訪問靜態圖片 http://192.168.10.110/game.jpg
2、動態頁面負載均衡測試:不斷刷新 http://192.168.10.110/index.jsp
因為負載均衡策略選擇輪詢的方式,所以動態請求會輪流轉發給Tomcat1和Tomcat2。
總結
本文全面介紹了Nginx反向代理與負載均衡的配置實踐,以及Tomcat應用服務器的部署與集成方案。主要內容包括:
- Nginx反向代理??:工作原理、基礎配置方法
- 負載均衡策略??:詳細解析6種主流算法及適用場景
- Tomcat核心知識??:架構原理、關鍵配置、數據源集成
- 實戰部署方案??:完整的Nginx+Tomcat負載均衡環境搭建
- 動靜分離實現??:智能區分處理動態請求和靜態資源
通過本指南,您可以構建出高性能、高可用的Web服務架構,有效應對高并發場景,提升系統穩定性和可擴展性。實際生產環境中,建議根據具體業務需求選擇合適的負載均衡策略,并配合健康檢查機制確保服務可靠性。