詳解Nginx負載均衡/反向代理/日志分析
Nginx 性能優(yōu)化之三大法寶
動靜分離
Web應(yīng)用中的資源可分為兩類:
☆ 動態(tài)內(nèi)容
需后端程序?qū)崟r生成的數(shù)據(jù)(如PHP/Java接口返回的JSON、用戶登錄狀態(tài)頁),通常由應(yīng)用服務(wù)器(如Tomcat、Node.js)處理。
☆ 靜態(tài)內(nèi)容
無需后端計算、可直接返回的文件(如圖片、CSS/JS、字體文件),由Nginx直接高效處理。
經(jīng)典配置
server {
listen 80;
server_name example.com;
# 動態(tài)請求:轉(zhuǎn)發(fā)到后端應(yīng)用服務(wù)器(如Tomcat/Node.js)
location /api/ {
proxy_pass http://backend_server:8080/; # 指向后端服務(wù)地址
proxy_set_header Host $host; # 傳遞原始請求頭
}
# 靜態(tài)資源:直接由Nginx從本地目錄返回
location ~* \.(jpg|jpeg|png|gif|css|js|woff|woff2|ico)$ {
root /var/www/static; # 靜態(tài)資源存放目錄
expires 30d; # 緩存30天(可選優(yōu)化)
}
# 默認動態(tài)請求(如PHP/HTML模板)
location / {
proxy_pass http://app_server:3000/; # 指向應(yīng)用服務(wù)器
}
}客戶端緩存
告知瀏覽器獲取的信息是在某個區(qū)間時間段是有效的,基本格式:
expires 30s; //表示把數(shù)據(jù)緩存30秒 expires 30m; //表示把數(shù)據(jù)緩存30分 expires 10h; //表示把數(shù)據(jù)緩存10小時 expires 3d; //表示把數(shù)據(jù)緩存3天
禁止緩存配置說明
add_header Cache-Control no-store;
案例:緩存圖片/js/css文件,緩存時間為1天
location ~* \.(jpg|jpeg|gif|png|js|css)$ {
expires 1d;
#add_header Cache-Control no-store;
}開啟 Gzip 壓縮
壓縮文件大小變小了,傳輸更快了,目前市場上大部分瀏覽器是支持GZIP的。
IE6以下支持不好,會出現(xiàn)亂碼情況。
http://nginx.org/en/docs/http/ngx_http_gzip_module.html
gzip on; # 第1行:開啟Gzip壓縮功能
gzip_min_length 1k; # 第2行:僅壓縮大于1KB的文件(小于1KB的壓縮后可能更大,不處理)
gzip_buffers 4 16k; # 第3行:壓縮時使用的緩沖區(qū)數(shù)量(4個)和大?。總€16KB)
gzip_http_version 1.1; # 第4行:兼容HTTP/1.1協(xié)議(主流瀏覽器均支持)
gzip_comp_level 5; # 第5行:壓縮級別(1-10),數(shù)字越大壓縮率越高但CPU消耗越大(推薦5~6)
gzip_types text/plain
text/css
text/javascript
application/javascript
application/x-javascript
image/jpeg
image/gif
image/png
image/x-ms-bmp; # 第6行:指定要壓縮的文件類型(優(yōu)先壓縮文本和圖片)
gzip_vary on; # 第7行:在響應(yīng)頭中添加Vary: Accept-Encoding,幫助緩存服務(wù)器區(qū)分壓縮/未壓縮版本
gzip_disable "MSIE [1-6]\."; # 第8行:禁用對IE6及以下版本的Gzip(兼容性問題)vary 是差異,多樣化的意思。
gzip_vary 是 Nginx 配置中的一條指令,它用于控制是否在響應(yīng)頭中設(shè)置 Vary: Accept-Encoding 頭部。具體來說:
gzip_vary on;:啟用時,Nginx 會在響應(yīng)頭中加入 Vary: Accept-Encoding,表示不同的客戶端可能會根據(jù)是否支持 gzip 壓縮來收到不同的響應(yīng)內(nèi)容。這有助于緩存服務(wù)器(如 CDN)緩存壓縮和未壓縮的內(nèi)容。
gzip_vary off;:禁用時,Nginx 不會在響應(yīng)頭中加入 Vary: Accept-Encoding,這意味著緩存服務(wù)器不會區(qū)分壓縮與未壓縮的內(nèi)容。這樣做通常會減少緩存的復(fù)雜性,但可能會導(dǎo)致某些情況緩存不一致。
| 指令 | 作用 | 推薦值/說明 |
| gzip on; | 開關(guān)Gzip功能 | 必須為 on才生效 |
| gzip_min_length 1k; | 最小壓縮文件大小 | 避免小文件壓縮后體積反而增大(默認20B~1k,建議1k~10k) |
| gzip_buffers 4 16k; | 壓縮緩沖區(qū)配置 | 4個16KB的緩沖區(qū)(根據(jù)服務(wù)器內(nèi)存調(diào)整) |
| gzip_http_version 1.1; | 兼容的HTTP協(xié)議版本 | 現(xiàn)代瀏覽器均支持1.1 |
| gzip_comp_level 5; | 壓縮級別 | 1(最快但壓縮率低)~10(最慢但壓縮率高),推薦5~6平衡性能與效果 |
| gzip_types | 指定壓縮的文件MIME類型 | 優(yōu)先壓縮文本(如HTML/CSS/JS)、常用圖片(如JPEG/PNG) |
| gzip_vary on; | 是否添加Vary頭 | 幫助CDN/代理服務(wù)器正確緩存壓縮與未壓縮版本 |
| gzip_disable "MSIE [1-6]\."; | 禁用低版本IE的Gzip | IE6對Gzip支持差,可能引發(fā)亂碼 |
常見壓縮類型:
文本類(.html/.css/.js)
矢量圖(.svg)
部分圖片(.png/.jpg,但已壓縮的圖片效果有限)
總結(jié)
| 優(yōu)化方向 | 核心目標 | 關(guān)鍵技術(shù) | 適用場景 |
| ??動靜分離?? | 提升資源處理效率,降低后端壓力 | Nginx路由分離(動態(tài)→后端,靜態(tài)→本地/CDN) | 所有Web應(yīng)用(尤其是高并發(fā)場景) |
| ??客戶端緩存?? | 減少重復(fù)傳輸,加速二次訪問 | expires/Cache-Control控制緩存時間 | 圖片、CSS/JS等長期不變的靜態(tài)資源 |
| ??Gzip壓縮?? | 減小傳輸體積,降低帶寬消耗 | gzip模塊壓縮文本/圖片 | 文本類資源(HTML/CSS/JS)、未高度壓縮的圖片 |
Nginx 日志分析
日志分類
| 日志類型 | 默認文件名 | 核心記錄內(nèi)容 | 默認存儲路徑(不同安裝方式) |
| 訪問日志 | access.log | 1、$remote_addr $upstream_status $request_time等變量組合(格式可自定義) 2、查看統(tǒng)計用戶的訪問信息與流量 | 源碼安裝:/usr/local/nginx/logs yum/dnf/apt 安裝:/var/log/nginx |
| 錯誤日志 | error.log | 1、配置語法錯誤、進程異常、連接超時等信息,含行號與錯誤碼(如[emerg] bind() failed) 2、錯誤信息以及重寫信息 | 同上 |
access 訪問日志
cat /var/log/nginx/access.log 或者 cat /usr/local/nginx/logs/access.log
日志參數(shù)詳解
參數(shù) | 意義 |
$remote_addr | 客戶端的ip地址(代理服務(wù)器,顯示代理服務(wù)ip) |
$remote_user | 用于記錄遠程客戶端的用戶名稱(一般為“-”) |
$time_local | 用于記錄訪問時間和時區(qū) |
$request | 用于記錄請求的url以及請求方法 |
$status | 響應(yīng)狀態(tài)碼,例如:200成功、404頁面找不到等 |
$body_bytes_sent | 給客戶端發(fā)送的文件主體內(nèi)容字節(jié)數(shù) |
$http_referer | 可以記錄用戶是從哪個鏈接訪問過來的 |
$http_user_agent | 用戶所使用的代理(一般為瀏覽器) |
$http_xforwarded_for | 可以記錄客戶端IP,通過代理服務(wù)器來記錄客戶端的IP地址 |
設(shè)置access.log訪問日志輸出格式與文件路徑:
vim /etc/nginx/nginx.conf 或者 vim /usr/local/nginx/conf/nginx.conf
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;配置完成后,重載Nginx,訪問站點,查看access.log日志,可以統(tǒng)計分析用戶的流量的相關(guān)情況。
nginx -s reload
error 錯誤日志
作用:用于Nginx排錯
error.log,默認記錄配置啟動錯誤信息和訪問請求錯誤信息。
cat /var/log/nginx/error.log 或者 cat /usr/local/nginx/logs/error.log
配置error_log:
vim /etc/nginx/nginx.conf 或者 vim /usr/local/nginx/conf/nginx.conf
在配置nginx.conf 的時候,有一項是指定錯誤日志的,默認情況下你不指定也沒有關(guān)系。
但有時出現(xiàn)問題時,是有必要記錄一下錯誤日志的,方便我們排查問題。
參考地址:https://nginx.org/en/docs/ngx_core_module.html#error_log
error_log 級別分為 debug, info, notice, warn, error, crit(從低到高)。
| 級別 | 含義 | 適用場景 |
| debug | 調(diào)試信息(最詳細) | 開發(fā)/排查復(fù)雜問題 |
| info | 一般性事件記錄 | 跟蹤運行狀態(tài) |
| notice | 重要但非錯誤事件 | 生產(chǎn)環(huán)境常規(guī)監(jiān)控 |
| warn | 警告事件(不影響服務(wù)) | 潛在問題預(yù)警 |
| error | ??默認級別??,錯誤事件 | 服務(wù)異常排查 |
| crit | Critical,嚴重錯誤 | 緊急問題(如權(quán)限拒絕) |
如果配置 error,會怎么樣呢?
Nginx 只會記錄 error級別及以上(即 error和 crit)的日志,而更低級別的日志(如 warn、notice、info、debug)將被忽略。
舉例如下
cat /var/log/nginx/error.log 或者 cat /usr/local/nginx/logs/error.log
注意:
crit 記錄的日志最少,而debug記錄的日志最多。
有些模塊突破了默認的error級別限制,也會記錄一些日志,比如進程啟動的一些notice通知。
小結(jié):
錯誤日志的作用:用來查看錯誤信息,通過提示的錯誤信息,排除錯誤。
GoAccess 輕量級日志分析
作用:針對Apache/Nginx訪問日志進行分析,優(yōu)點:輕量級、開源、帶圖形化界面!
什么是GoAccess?
GoAccess 是一款開源的且具有交互視圖界面的 實時 Web 日志分析工具,通過你的 Web 瀏覽器或者 Linux 系統(tǒng)下的 終端程序 即可訪問。
能為系統(tǒng)管理員提供快速且有價值的 HTTP 統(tǒng)計,并以在線可視化服務(wù)器的方式呈現(xiàn)。
安裝GoAccess:
安裝 GoAccess dnf install goaccess -y 如果安裝GoAccess不成功,可以先完善一下 EPEL 倉庫 安裝 EPEL 倉庫(Extra Packages for Enterprise Linux) dnf install epel-release -y
說明:
EPEL 是 RedHat/CentOS 官方維護的擴展軟件源,提供大量常用但非默認包含的工具(如 GoAccess、htop 等)。
Nginx 默認訪問日志通常位于
/usr/local/nginx/logs/access.log(若編譯安裝時未修改路徑)
或
/var/log/nginx/access.log(若通過包管理器安裝)
本例以 Nginx 源碼編譯安裝到 /usr/local/nginx/ 為例
cd /usr/local/nginx/
注意:GoAccess分析的結(jié)果往往是一個html網(wǎng)頁,如果想直接預(yù)覽,建議直接把內(nèi)容放置于Nginx訪問目錄
① 離線分析
離線分析,會生成靜態(tài) HTML 報告(推薦生產(chǎn)環(huán)境)
通過以下命令對訪問日志進行分析,并將結(jié)果輸出為 HTML 文件(便于通過瀏覽器查看)
goaccess -f /usr/local/nginx/logs/access.log --log-format=COMBINED > /usr/local/nginx/html/itheimadevops/report.html
或者
goaccess -f /usr/local/nginx/logs/access.log --log-format=COMBINED > report.html
或者
goaccess -f /var/log/nginx/access.log --log-format=COMBINED > report.html
-f:指定文件
--log-format:分析的文件格式
COMBINED代表組合日志格式(XLF/ELF) Apache | Nginx
COMMON代表通用日志格式(CLF) ApacheNginx server 配置參考:
vi /usr/local/nginx/conf/nginx.conf
...
server {
# 監(jiān)聽端口
listen 80;
# 配置域名
server_name www.itheimadevops.com;
# 配置目錄
root html/itheimadevops;
access_log logs/www.itheimadevops.com.access.log main;
error_log logs/www.itheimadevops.com.error.log;
# 配置uri匹配規(guī)則
location / {
index index.html index.htm;
}
location ~ \.(jpg|jpeg|gif|png|js|css)$ {
add_header Cache-Control no-store;
}
}
...查看 report.html
goaccess -f /var/log/nginx/access.log --log-format=COMBINED > report.html ls -hl report.html goaccess -f /usr/local/nginx/logs/access.log --log-format=COMBINED > report.html ls -hl report.html
- server1(dnf 版 Nginx)日志路徑:
/var/log/nginx/access.log - server2(源碼版 Nginx)日志路徑:
/usr/local/nginx/logs/access.log - 作用:用 goaccess 解析 Nginx 訪問日志,生成可視化報表
report.html
② 實時分析
除生成靜態(tài) HTML 外,GoAccess 還支持 終端實時動態(tài)展示(適合快速排查問題)
goaccess /usr/local/nginx/logs/access.log \ --no-global-config \ --log-format='%h %^ %^ [%d:%t %^] "%r" %s %b "%R" "%u"' \ --date-format='%d/%b/%Y' \ --time-format='%H:%M:%S' 或者 goaccess /var/log/nginx/access.log \ --no-global-config \ --log-format='%h %^ %^ [%d:%t %^] "%r" %s %b "%R" "%u"' \ --date-format='%d/%b/%Y' \ --time-format='%H:%M:%S'
更多參考:https://www.goaccess.cc/?mod=man
Nginx 企業(yè)級日志分析實戰(zhàn)經(jīng)典案例
GoAccess 不僅能生成基礎(chǔ)的可視化報告,更能通過靈活的命令行參數(shù)與日志分析,幫助企業(yè)快速定位關(guān)鍵問題(如高頻攻擊 IP、異常 404 請求、熱門業(yè)務(wù)路徑)。
本章聚焦三大典型企業(yè)級場景,結(jié)合實戰(zhàn)命令與結(jié)果解讀,助你掌握日志分析的“進階用法”。
統(tǒng)計訪問量最高的IP地址
在生成日志分析報告時,GoAccess 默認會統(tǒng)計并展示 “Top IPs”(訪問量最高的 IP 地址列表)。
☆ 場景背景
企業(yè)的 Web 服務(wù)可能面臨兩類與 IP 相關(guān)的風險:
- 正常高頻訪問:如內(nèi)部員工頻繁調(diào)用 API、爬蟲程序抓取公開數(shù)據(jù)(需評估是否合理)。
- 惡意行為:如 DDoS 攻擊(大量 IP 短時間內(nèi)發(fā)起請求)、暴力破解(針對登錄接口的重復(fù)嘗試)、爬蟲違規(guī)采集(超出正常頻率)。
通過統(tǒng)計訪問量最高的 IP,可以快速鎖定 “誰在頻繁訪問我的服務(wù)”,進而判斷是否需要封禁、限流或進一步分析其行為
☆ 腳本實現(xiàn)
# 提取日志中的 IP(假設(shè)為每行第一個字段,符合 Nginx 默認日志格式)并統(tǒng)計頻次,按次數(shù)降序排序,取前 10
awk '{print $1}' /usr/local/nginx/logs/access.log | sort | uniq -c | sort -nr | head -n 10
說明:
awk '{print $1}':提取日志每行的第一個字段(通常是客戶端 IP,Nginx 默認日志格式中 $1為 IP)。
sort:對 IP 列表進行排序(uniq -c要求輸入已排序)。
uniq -c:統(tǒng)計每個唯一 IP 的出現(xiàn)次數(shù)(-c表示計數(shù))。
sort -nr:按計數(shù)結(jié)果降序排序(-n數(shù)值排序,-r逆序)。
head -n 10:僅顯示前 10 條結(jié)果。統(tǒng)計404錯誤的請求
☆ 場景背景
HTTP 404 狀態(tài)碼表示 “請求的資源不存在”,可能由以下原因?qū)е拢?/p>
- 用戶側(cè)問題:用戶手動輸入了錯誤的 URL、點擊了過期的書簽或外鏈。
- 業(yè)務(wù)側(cè)問題:前端頁面鏈接配置錯誤(如前端代碼中的 API 地址拼寫錯誤)、后端服務(wù)刪除了文件但未更新前端引用、CDN 緩存了舊版本的無效鏈接。
- 攻擊行為:掃描器嘗試訪問常見的敏感路徑(如 /admin.php、/config.json),試圖探測系統(tǒng)漏洞。
通過統(tǒng)計 404 錯誤請求,可以快速定位 “哪些資源被頻繁訪問但不存在”,進而修復(fù)業(yè)務(wù)邏輯或加固安全防護。
☆ 腳本實現(xiàn)
# grep 查找關(guān)鍵狀態(tài)碼 404 grep '404' /usr/local/nginx/logs/access.log 或者 grep '404' /var/log/nginx/access.log # 提取所有狀態(tài)碼為 404 的日志行(Nginx 默認日志格式中狀態(tài)碼是第9個字段) awk '$9 == 404' /usr/local/nginx/logs/access.log 或者 awk '$9 == 404' /var/log/nginx/access.log
如果Nginx站點很正常,一般來講就沒有404,可以考慮查找一下200
awk '$9 == 200' /usr/local/nginx/logs/access.log|more
進階實現(xiàn)
# 進階:提取 404 請求的路徑(第7個字段),統(tǒng)計頻次并排序
awk '$9 == 404 {print $7}' /usr/local/nginx/logs/access.log | sort | uniq -c | sort -nr | head -n 10
或者
awk '$9 == 404 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -n 10
或者
awk '$9 == 404' /usr/local/nginx/logs/access.log | awk '{ print $7}' | sort | uniq -c | sort -nr | head -n 10
或者
awk '$9 == 404' /var/log/nginx/access.log | awk '{ print $7}' | sort | uniq -c | sort -nr | head -n 10統(tǒng)計最熱門的URL
☆ 場景背景
“最熱門的 URL” 反映了用戶最常訪問的頁面或接口,是企業(yè)分析 “用戶關(guān)注什么” 和 “業(yè)務(wù)重點在哪里” 的關(guān)鍵指標。通過統(tǒng)計熱門 URL,可以:
- 優(yōu)化資源配置:為高流量頁面分配更多服務(wù)器資源(如 CDN 加速、數(shù)據(jù)庫緩存)。
- 改進用戶體驗:分析熱門頁面的加載速度、跳出率(需結(jié)合其他工具),針對性優(yōu)化交互設(shè)計。
- 驗證業(yè)務(wù)策略:檢查推廣活動鏈接(如營銷頁 /promotion/2025)是否達到預(yù)期流量,或核心功能(如支付頁 /checkout)是否易用。
☆ 腳本實現(xiàn)
# 提取日志中的請求路徑(第11個字段),統(tǒng)計頻次并排序,取前 10
awk '{print $11}' /usr/local/nginx/logs/access.log | sort | uniq -c | sort -nr | head -n 10
或者
awk '{print $11}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -n 10日志輪轉(zhuǎn)
作用:利用Shell腳本對日志進行切割,把大的訪問日志切割為一個一個小日志,方便后期存儲以及查看分析
☆腳本實現(xiàn)
mkdir /scripts cd /scripts vim logrotate.sh ------------------分割線------------------- #!/bin/bash date_info=$(date +%F-%H-%M) mv /usr/local/nginx/logs/access.log /usr/local/nginx/logs/access.log.$date_info /usr/local/nginx/sbin/nginx -s reload ------------------分割線------------------- chmod +x /scripts/logrotate.sh
☆配置 crontab
crontab -e * * * * * /bin/bash /scripts/logrotate.sh &>/dev/null 或者 0 */6 * * * /bin/bash /scripts/logrotate.sh &>/dev/null 或者 0 * * * * /bin/bash /scripts/logrotate.sh &>/dev/null 30 2 * * * /bin/bash /scripts/logrotate.sh &>/dev/null
改進版
mv /usr/local/nginx/logs/access.log /usr/local/nginx/logs/access.log.$(date +%F_%H-%M-%S) && /usr/local/nginx/sbin/nginx -s reopen
nginx -s reload 與 nginx -s reopen 對比表
對比項 | reload | reopen |
主要用途 | 重新加載配置文件 | 重新打開日志文件 |
是否創(chuàng)建新日志文件 | ? 否 | ? 是 |
是否重啟工作進程 | ? 是(平滑重啟) | ? 否(繼續(xù)使用原進程) |
是否重新加載配置 | ? 是 | ? 否 |
是否中斷現(xiàn)有連接 | ? 否(優(yōu)雅關(guān)閉) | ? 否 |
配置文件語法檢查 | ? 會進行檢查 | ? 不會檢查 |
典型使用場景 | nginx.conf 配置變更后生效 | 日志切割/輪轉(zhuǎn)(配合 logrotate) |
執(zhí)行命令示例 |
|
|
工作原理簡述
reload:
- 主進程檢查新配置語法
- 啟動新工作進程(加載新配置)
- 優(yōu)雅關(guān)閉舊工作進程
reopen:
- 主進程通知工作進程關(guān)閉當前日志文件
- 工作進程重新打開日志文件(按配置路徑)
- 若文件不存在則自動創(chuàng)建
總結(jié)
日志輪轉(zhuǎn)的本質(zhì)就是把一個大的日志切割為若干個小的日志,防止文件過大。
Nginx 反向代理
反向代理(Reverse Proxy)是位于 客戶端與后端服務(wù)器之間 的中間設(shè)備(或服務(wù)),客戶端直接訪問代理服務(wù)器,代理服務(wù)器再將請求轉(zhuǎn)發(fā)給內(nèi)部的后端服務(wù)器,并將后端服務(wù)器的響應(yīng)返回給客戶端。
反向代理的好處:
- 隱藏后端架構(gòu):客戶端只與代理服務(wù)器交互,后端服務(wù)的IP、端口、部署細節(jié)(如多臺服務(wù)器集群)對客戶端不可見。
- 負載均衡:將客戶端請求分發(fā)到多臺后端服務(wù)器,提升整體處理能力(后續(xù)章節(jié)會深入講解)。
- 安全防護:代理服務(wù)器可過濾惡意請求(如SQL注入、XSS)、限制訪問IP、提供SSL加密(HTTPS終止)。
- 統(tǒng)一入口:通過一個域名/端口(如 http://example.com)訪問多個后端服務(wù)(如API、靜態(tài)資源、管理后臺)。
環(huán)境準備
準備虛擬機
角色 | IP | 主機名 | 功能 |
nginx1 | 192.168.88.101 | nginx1.itcast.cn | 代理服務(wù)器 |
nginx2 | 192.168.88.102 | nginx2.itcast.cn | 后端服務(wù)器 |
修改主機名和 hosts
hostnamectl set-hostname nginx1.itcast.cn && bash hostnamectl set-hostname nginx2.itcast.cn && bash cat >/etc/hosts<<EOF 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.88.101 nginx1 nginx1.itcast.cn 192.168.88.102 nginx2 nginx2.itcast.cn EOF
關(guān)閉防火墻與 SELinux
iptables -F systemctl stop firewalld systemctl disable firewalld setenforce 0 sed -i '/SELINUX=enforcing/cSELINUX=disabled' /etc/selinux/config
安裝依賴包以及時間同步
# 安裝依賴包
yum install vim wget rsync net-tools epel-release -y
# 更新安裝ntp時間服務(wù)器(可選)
yum install ntpsec -y
ntpdate cn.ntp.org.cn
說明:
ntpsec?:是 NTP (Network Time Protocol) 的一個安全增強分支版本,用于系統(tǒng)時間同步;
cn.ntp.org.cn:是中國國家授時中心維護的 NTP 服務(wù)器地址
# 如果Linux服務(wù)器通不了外網(wǎng),可以考慮配置一下DNS解析地址
cat >/etc/resolv.conf<<EOF
nameserver 192.168.88.2
nameserver 114.114.114.114
EOF部署實戰(zhàn)
配置后端服務(wù)器
在后端服務(wù)器nginx2上執(zhí)行
dnf安裝的nginx
[root@nginx2 ~]# dnf install nginx -y
修改nginx服務(wù)運行端口為8080
[root@nginx2 ~]# vim /etc/nginx/nginx.conf
...
server {
listen 8080;
listen [::]:8080;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
...
[root@nginx2 ~]# cat /etc/nginx/nginx.conf
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 8080;
listen [::]:8080;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers PROFILE=SYSTEM;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
[root@nginx2 ~]# cat >/usr/share/nginx/html/index.html <<EOF
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>后端Web服務(wù)器</title>
</head>
<body>
這是后端Web服務(wù)器
</body>
</html>
EOF
[root@nginx2 ~]# cat /usr/share/nginx/html/index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>后端Web服務(wù)器</title>
</head>
<body>
這是后端Web服務(wù)器
</body>
</html>
[root@nginx2 ~]#
檢查nginx配置文件是否正確
[root@nginx2 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@nginx2 ~]# systemctl restart nginx
[root@nginx2 ~]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; preset: disabled)
Active: active (running) since Thu 2025-12-11 11:34:51 CST; 4s ago
Process: 29371 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Process: 29373 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 29374 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Main PID: 29375 (nginx)
Tasks: 3 (limit: 22927)
Memory: 3.0M
CPU: 25ms
CGroup: /system.slice/nginx.service
├─29375 "nginx: master process /usr/sbin/nginx"
├─29376 "nginx: worker process"
└─29377 "nginx: worker process"
Dec 11 11:34:51 nginx2.itcast.cn systemd[1]: Starting The nginx HTTP and reverse proxy server...
Dec 11 11:34:51 nginx2.itcast.cn nginx[29373]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Dec 11 11:34:51 nginx2.itcast.cn nginx[29373]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Dec 11 11:34:51 nginx2.itcast.cn systemd[1]: Started The nginx HTTP and reverse proxy server.
[root@nginx2 ~]# systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
[root@nginx2 ~]# netstat -pantul|grep nginx
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 30551/nginx: master
tcp6 0 0 :::8080 :::* LISTEN 30551/nginx: master
[root@nginx2 ~]#源碼安裝的nginx
[root@nginx2 ~]# ls /usr/local/nginx/
client_body_temp fastcgi_temp logs sbin uwsgi_temp
conf html proxy_temp scgi_temp
[root@nginx2 ~]# ls /usr/local/nginx/conf/
fastcgi.conf mime.types scgi_params.default
fastcgi.conf.default mime.types.default uwsgi_params
fastcgi_params nginx.conf uwsgi_params.default
fastcgi_params.default nginx.conf.bak win-utf
koi-utf nginx.conf.default
koi-win scgi_params
[root@nginx2 ~]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx2 ~]# cat /usr/local/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 8080;
server_name 192.168.88.102;
root /usr/local/nginx/html;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
[root@nginx2 ~]# 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
[root@nginx2 ~]# nginx -s reload
[root@nginx2 ~]# cat >/usr/local/nginx/html/index.html <<EOF
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>后端Web服務(wù)器</title>
</head>
<body>
這是后端Web服務(wù)器
</body>
</html>
EOF
[root@nginx2 ~]# cat /usr/local/nginx/html/index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>后端Web服務(wù)器</title>
</head>
<body>
這是后端Web服務(wù)器
</body>
</html>
[root@nginx2 ~]# systemctl restart nginx
[root@nginx2 ~]# systemctl status nginx
● nginx.service - Nginx Web Server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: d>
Active: active (running) since Tue 2026-03-24 09:40:53 CST; 5s ago
Process: 4706 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, sta>
Process: 4708 ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/co>
Main PID: 4709 (nginx)
Tasks: 2 (limit: 22927)
Memory: 2.1M
CPU: 17ms
CGroup: /system.slice/nginx.service
├─4709 "nginx: master process /usr/local/nginx/sbin/nginx -c /usr>
└─4710 "nginx: worker process"
Mar 24 09:40:53 nginx2.itcast.cn systemd[1]: Starting Nginx Web Server...
Mar 24 09:40:53 nginx2.itcast.cn systemd[1]: Started Nginx Web Server.
[root@nginx2 ~]# netstat -pantul|grep nginx
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 4709/nginx: master
[root@nginx2 ~]#測試后端服務(wù)器的Web服務(wù)
[root@nginx2 ~]# curl 192.168.88.102:8080
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>后端Web服務(wù)器</title>
</head>
<body>
這是后端Web服務(wù)器
</body>
</html>
[root@nginx2 ~]#http://192.168.88.102:8080/
配置代理服務(wù)器
在前端服務(wù)器nginx1上執(zhí)行
dnf安裝的nginx
[root@nginx1 ~]# dnf install nginx -y
修改nginx1配置文件,對接nginx2
[root@nginx1 ~]# find / -name nginx.conf
/etc/nginx/nginx.conf
/usr/lib/sysusers.d/nginx.conf
[root@nginx1 ~]# vim /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name _;
# root /usr/share/nginx/html;
location / {
proxy_pass http://192.168.88.102:8080; # 關(guān)鍵!指定后端服務(wù)器的IP和端口
proxy_set_header Host $host; # 傳遞原始請求的Host頭(重要?。?
proxy_set_header X-Real-IP $remote_addr; # 傳遞客戶端真實IP(后端可通過此頭獲取)
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 傳遞完整的代理鏈路IP
}
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
# root html;
}
}
}
[root@nginx1 ~]# cat /etc/nginx/nginx.conf
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name _;
# root /usr/share/nginx/html;
location / {
proxy_pass http://192.168.88.102:8080; # 關(guān)鍵!指定后端服務(wù)器的IP和端口
proxy_set_header Host $host; # 傳遞原始請求的Host頭(重要!)
proxy_set_header X-Real-IP $remote_addr; # 傳遞客戶端真實IP(后端可通過此頭獲?。?
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 傳遞完整的代理鏈路IP
}
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers PROFILE=SYSTEM;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
[root@nginx1 ~]#源碼安裝的nginx
[root@nginx1 ~]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx1 ~]# cat /usr/local/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name _;
# root /usr/local/nginx/html;
location / {
proxy_pass http://192.168.88.102:8080; # 關(guān)鍵!指定后端服務(wù)器的IP和端口
proxy_set_header Host $host; # 傳遞原始請求的Host頭(重要?。?
proxy_set_header X-Real-IP $remote_addr; # 傳遞客戶端真實IP(后端可通過此頭獲?。?
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 傳遞完整的代理鏈路IP
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
[root@nginx1 ~]# 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
[root@nginx1 ~]# nginx -s reload
[root@nginx1 ~]#檢查Nginx配置文件并啟動Nginx服務(wù)
[root@nginx1 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@nginx1 ~]# systemctl restart nginx
[root@nginx1 ~]# systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
[root@nginx1 ~]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: d>
Active: active (running) since Sat 2025-12-13 12:07:24 CST; 7s ago
Main PID: 30749 (nginx)
Tasks: 3 (limit: 22926)
Memory: 3.0M
CPU: 37ms
CGroup: /system.slice/nginx.service
├─30749 "nginx: master process /usr/sbin/nginx"
├─30750 "nginx: worker process"
└─30751 "nginx: worker process"
Dec 13 12:07:24 nginx1.itcast.cn systemd[1]: Starting The nginx HTTP and rever>
Dec 13 12:07:24 nginx1.itcast.cn nginx[30747]: nginx: the configuration file />
Dec 13 12:07:24 nginx1.itcast.cn nginx[30747]: nginx: configuration file /etc/>
Dec 13 12:07:24 nginx1.itcast.cn systemd[1]: Started The nginx HTTP and revers>
# nginx -s reload # 可選驗證測試
http://192.168.88.101/
http://192.168.88.102:8080/
Nginx代理服務(wù)器暴力broken測試
server {
listen 80;
server_name _;
location / {
return 500 "broken\n";
}
}[root@nginx1 ~]# cd /etc/nginx
[root@nginx1 nginx]# pwd
/etc/nginx
[root@nginx1 nginx]# vim nginx.conf
[root@nginx1 nginx]# cat nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
#include /etc/nginx/conf.d/*.conf;
server {
listen 80;
server_name _;
location / {
return 500 "broken\n";
}
#root /usr/share/nginx/html;
# location / {
# proxy_pass http://192.168.88.102:8080; # 關(guān)鍵!指定后端服務(wù)器的IP和端口
# proxy_set_header Host $host; # 傳遞原始請求的Host頭(重要?。?
# proxy_set_header X-Real-IP $remote_addr; # 傳遞客戶端真實IP(后端可通過此頭獲取)
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 傳遞完整的代理鏈路IP
# }
#include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
[root@nginx1 nginx]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@nginx1 nginx]# nginx -s reload
[root@nginx1 nginx]# curl 127.0.0.1
broken
[root@nginx1 nginx]#http://192.168.88.101/
結(jié)論1:
Nginx 在沒有配置
location和root時,會使用默認 root/usr/share/nginx/html提供靜態(tài)資源。
結(jié)論2:
只要定義了
location /,就會覆蓋默認行為。
結(jié)論3:
return指令優(yōu)先級非常高,可以直接終止請求處理流程。
Nginx 的配置是具備兜底機制的,即使沒有顯式配置 root 和 location,也會使用默認 root 提供服務(wù)。因此在排查問題時,如果發(fā)現(xiàn)配置改了但結(jié)果沒變,要考慮是否命中了默認行為或者其他 location。
HTTP/1.0與HTTP/1.1
HTTP/1.1 和 HTTP/1.0 是 Web 協(xié)議演進中的兩個重要版本,主要區(qū)別如下:
主要區(qū)別對比表
| 特性 | HTTP/1.0 | HTTP/1.1 |
| 連接方式 | 默認短連接,每個請求建立新TCP連接 | 默認長連接(Keep-Alive),連接可復(fù)用 |
| Host頭 | 可選,不支持虛擬主機 | 必需,支持多域名共享IP |
| 緩存控制 | 簡單的 Expires、Pragma | 強大的 Cache-Control、ETag、Last-Modified |
| 狀態(tài)碼 | 基本狀態(tài)碼 | 新增 100 Continue, 206 Partial Content 等 |
| 分塊傳輸 | 不支持 | 支持 Transfer-Encoding: chunked |
| 管道化 | 不支持 | 支持(但有限制) |
| 帶寬優(yōu)化 | 不支持范圍請求 | 支持 Range 和 Accept-Ranges |
| 錯誤處理 | 簡單 | 更完善的錯誤處理和恢復(fù)機制 |
| 請求方法 | GET, POST, HEAD | 新增 OPTIONS, PUT, DELETE, TRACE, CONNECT |
[root@nginx1 ~]# vim /etc/nginx/nginx.conf
[root@nginx1 ~]# cat /etc/nginx/nginx.conf
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name _;
# root /usr/share/nginx/html;
location / {
proxy_http_version 1.1;
proxy_pass http://192.168.88.102:8080; # 關(guān)鍵!指定后端服務(wù)器的IP和端口
proxy_set_header Host $host; # 傳遞原始請求的Host頭(重要?。?
proxy_set_header X-Real-IP $remote_addr; # 傳遞客戶端真實IP(后端可通過此頭獲取)
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 傳遞完整的代理鏈路IP
proxy_set_header X-Original-Protocol $server_protocol;
}
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers PROFILE=SYSTEM;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
[root@nginx1 ~]#
[root@nginx1 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@nginx1 ~]# nginx -s reload訪問代理服務(wù)器地址
http://192.168.88.101/
總結(jié)
代理一共有兩種:(正向代理) + (反向代理)
1、正向代理用戶可以感知到,比較典型應(yīng)用(科學上網(wǎng))
2、反向代理用戶無感知,比較典型的應(yīng)用(請求轉(zhuǎn)發(fā),更多應(yīng)用在于負載均衡技術(shù))
Nginx 負載均衡
四層負載 vs 七層負載
① 底層實現(xiàn) => 四層負載均衡基于網(wǎng)絡(luò)層與傳輸層,也就是IP + Port(套接字 socket)實現(xiàn)請求轉(zhuǎn)發(fā);七層負載基于應(yīng)用層,通過URL地址請求轉(zhuǎn)發(fā)
② 性能不同 => 四層相當于轉(zhuǎn)發(fā)器,效率更高;七層需要通過URL判斷才能實現(xiàn)轉(zhuǎn)發(fā),需要做額外的處理
③ 安全性不同 => 七層需要對用戶URL請求,判斷可以屏蔽異常請求,相對而言更加安全
環(huán)境準備
角色 | IP | 主機名 | 功能 |
lb1 | 192.168.88.100 | lb1.itcast.cn | 負載均衡 |
web1 | 192.168.88.101 | web1.itcast.cn | Web服務(wù) |
web2 | 192.168.88.102 | web2.itcast.cn | Web服務(wù) |
修改IP、主機名和域名解析
hostnamectl set-hostname lb1.itcast.cn && bash hostnamectl set-hostname web1.itcast.cn && bash hostnamectl set-hostname web2.itcast.cn && bash cat >/etc/hosts<<EOF 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.88.100 lb1 lb1.itcast.cn 192.168.88.101 web1 web1.itcast.cn 192.168.88.102 web2 web2.itcast.cn EOF
關(guān)閉防火墻與 SELinux
iptables -F systemctl stop firewalld systemctl disable firewalld setenforce 0 sed -i '/SELINUX=enforcing/cSELINUX=disabled' /etc/selinux/config
安裝依賴包時間同步
yum install vim wget rsync net-tools epel-release -y yum install ntpsec -y ntpdate cn.ntp.org.cn cat >/etc/resolv.conf<<EOF nameserver 192.168.88.2 nameserver 114.114.114.114 EOF
NTPsec vs Chrony
| 特性 | NTPsec | Chrony |
| 起源 | 從經(jīng)典 NTP(ntpd)分支而來,由 NTPsec 團隊維護 | 獨立開發(fā),最初為嵌入式系統(tǒng)設(shè)計 |
| 設(shè)計目標 | 增強安全性和性能,修復(fù) ntpd 的歷史問題 | 快速同步、低延遲,適合不穩(wěn)定網(wǎng)絡(luò)環(huán)境 |
| 社區(qū)活躍度 | 活躍,但用戶基數(shù)小于 Chrony | 廣泛采用,尤其在云環(huán)境和現(xiàn)代 Linux 發(fā)行版 |
安裝nginx
三個服務(wù)器都要按照nginx
如果網(wǎng)絡(luò)有問題,請執(zhí)行以下命令
cat >/etc/resolv.conf<<EOF nameserver 192.168.88.2 nameserver 114.114.114.114 EOF
systemctl status nginx --no-pager
配置 Web1 & Web2
這節(jié)課我們聚焦 Nginx 負載均衡,關(guān)于 backend 服務(wù),用 html 簡單內(nèi)容代替。
# 在LB1上執(zhí)行,統(tǒng)一 一下三臺的nginx配置文件(可選) scp /etc/nginx/nginx.conf 192.168.88.101:/etc/nginx/ scp /etc/nginx/nginx.conf 192.168.88.102:/etc/nginx/ # 在 Web1 上執(zhí)行 echo "This is Web Server1" > /usr/share/nginx/html/index.html 或者 echo "This is Web Server1" > /usr/local/nginx/html/index.html # 在 Web2 上執(zhí)行 echo "This is Web Server2" > /usr/share/nginx/html/index.html 或者 echo "This is Web Server2" > /usr/local/nginx/html/index.html
驗證測試
curl 127.0.0.1
配置 LB1
下面的操作,都是在 LB1 上操作
第一步:查看 nginx.cnf
在 LB1 上,備份配置文件nginx.conf,然后刪除注釋與空行
第一步,備份
[root@lb1 ~]# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak # 這是 dnf/yum 安裝的 Nginx
第二步,去掉注釋,空行
[root@lb1 ~]# grep -Ev '#|^$' /etc/nginx/nginx.conf.bak > /etc/nginx/nginx.conf
第三步,簡單查看配置
[root@lb1 ~]# cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
[root@lb1 ~]#第二步:配置負載均衡
Nginx 在 http 塊中實現(xiàn)七層負載均衡,默認使用輪詢算法;同時也支持通過 stream 塊實現(xiàn)四層負載均衡
在 LB1 上操作
vim /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# include /etc/nginx/conf.d/*.conf;
#################### 配置開始 ######################
upstream my_web_service {
server 192.168.88.101:80;
server 192.168.88.102:80;
}
#################### 配置結(jié)束 ######################
server {
listen 80;
listen [::]:80;
#################### 配置開始 ######################
server_name 192.168.88.100; # 替換為實際域名或 IP
location / {
proxy_pass http://my_web_service; # 將請求轉(zhuǎn)發(fā)到負載均衡組
proxy_set_header HOST $host;
}
#################### 配置結(jié)束 ######################
# server_name _;
# root /usr/share/nginx/html;
# include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}第三步:重載配置,驗證測試第三步:重載配置,驗證測試
在 LB1 上操作
nginx -t nginx -s reload [root@lb1 ~]# curl 192.168.88.100 This is Web Server1 [root@lb1 ~]# curl 192.168.88.100 This is Web Server2 [root@lb1 ~]# curl 192.168.88.100 This is Web Server1 [root@lb1 ~]# curl 192.168.88.100 This is Web Server2
注意:如果無法訪問Nginx Web服務(wù),請在所有Linux服務(wù)器上執(zhí)行以下命令!
sed -i -r 's/SELINUX=[ep].*/SELINUX=disabled/g' /etc/selinux/config setenforce 0 systemctl stop firewalld &> /dev/null systemctl disable firewalld &> /dev/null iptables -F iptables -t nat -F iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT
回到瀏覽器,多次訪問,會發(fā)現(xiàn)
頁面在 Web1 和 Web2 之間來回切換(這是為了方便驗證而設(shè)計的內(nèi)容),從而驗證負載均衡配置成功。
炫酷技能(拓展)
旋轉(zhuǎn)星空
cat >index.html<<EOF
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<style>
body {
background: #060e1b;
overflow: hidden;
}
</style>
</HEAD>
<BODY>
<canvas id="canvas"></canvas>
<script>
"use strict";
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
w = canvas.width = window.innerWidth,
h = canvas.height = window.innerHeight,
hue = 217,
stars = [],
count = 0,
maxStars = 1400;
// Thanks @jackrugile for the performance tip! https://codepen.io/jackrugile/pen/BjBGoM
// Cache gradient
var canvas2 = document.createElement('canvas'),
ctx2 = canvas2.getContext('2d');
canvas2.width = 100;
canvas2.height = 100;
var half = canvas2.width/2,
gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half);
gradient2.addColorStop(0.025, '#fff');
gradient2.addColorStop(0.1, 'hsl(' + hue + ', 61%, 33%)');
gradient2.addColorStop(0.25, 'hsl(' + hue + ', 64%, 6%)');
gradient2.addColorStop(1, 'transparent');
ctx2.fillStyle = gradient2;
ctx2.beginPath();
ctx2.arc(half, half, half, 0, Math.PI * 2);
ctx2.fill();
// End cache
function random(min, max) {
if (arguments.length < 2) {
max = min;
min = 0;
}
if (min > max) {
var hold = max;
max = min;
min = hold;
}
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function maxOrbit(x,y) {
var max = Math.max(x,y),
diameter = Math.round(Math.sqrt(max*max + max*max));
return diameter/2;
}
var Star = function() {
this.orbitRadius = random(maxOrbit(w,h));
this.radius = random(60, this.orbitRadius) / 12;
this.orbitX = w / 2;
this.orbitY = h / 2;
this.timePassed = random(0, maxStars);
this.speed = random(this.orbitRadius) / 50000;
this.alpha = random(2, 10) / 10;
count++;
stars[count] = this;
}
Star.prototype.draw = function() {
var x = Math.sin(this.timePassed) * this.orbitRadius + this.orbitX,
y = Math.cos(this.timePassed) * this.orbitRadius + this.orbitY,
twinkle = random(10);
if (twinkle === 1 && this.alpha > 0) {
this.alpha -= 0.05;
} else if (twinkle === 2 && this.alpha < 1) {
this.alpha += 0.05;
}
ctx.globalAlpha = this.alpha;
ctx.drawImage(canvas2, x - this.radius / 2, y - this.radius / 2, this.radius, this.radius);
this.timePassed += this.speed;
}
for (var i = 0; i < maxStars; i++) {
new Star();
}
function animation() {
ctx.globalCompositeOperation = 'source-over';
ctx.globalAlpha = 0.8;
ctx.fillStyle = 'hsla(' + hue + ', 64%, 6%, 1)';
ctx.fillRect(0, 0, w, h)
ctx.globalCompositeOperation = 'lighter';
for (var i = 1, l = stars.length; i < l; i++) {
stars[i].draw();
};
window.requestAnimationFrame(animation);
}
animation();
</script>
</BODY>
</HTML>
EOF
黑客數(shù)字雨
cat >index.html<<EOF
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<style>
/*Twitter @locoalien*/
/*Sitio web www.locoaliensoft.com*/
/*www.facebook.com/CulturaInformatica*/
* {margin: 0; padding: 0;}
canvas {display: block;}
body {background: black;}
</style>
</HEAD>
<BODY>
<html>
<head>
<title>Hacking locoalien Matrix console</title>
<meta charset="UTF-8">
</head>
<body>
<canvas id="locoalien"></canvas>
<script type="text/javascript">
</script>
</body>
</html>
<script>
//*--------------------------------------*
//* Desarrollado por Locoalien *
//* Twitter @locoalien *
//* Sitio web: www.locoaliensoft.com *
//*--------------------------------------*
//+++++++++++++++++++++++++++++++++++++
// El objetivo de este ejemplo es aprender a dar animacion y utilizar las propiedades
// Mas comunes de JavaScript. Veremos el poder que tiene HTML5 implementando el Canvas
// Espero les guste este ejemplo
// Para mas informacion visitar nuestra pagina de Facebook: https://www.facebook.com/CulturaInformatica
//+++++++++++++++++++++++++++++++++++++
window.onload = hacking;//Llamamos a la funcion despues de que el documento ha sido cargado completamente
function hacking(){
var c = document.getElementById("locoalien");
c.height = window.innerHeight; //innerHeight se utiliza para saber la altura de la pantalla
c.width = window.innerWidth; //innerHeight se utiliza para saber la altura de la pantalla
var letraTam=12; //Tama?o de la letras por pixel
var columnas=c.width/letraTam; //El ancho dividido por el tamano que tendra las letras
var Texto="0"; //El testo que aparecera en pantalla
Texto=Texto.split("");//La función split() permite dividir una cadena de caracteres (string) en varios bloques y crear un array con estos
var Texto2="1";
Texto2=Texto2.split("");
var letras=[];
for(var i=0; i<columnas;i++){
letras[i]=1;//Siver para saber la cantidad de letras que tendra en la pantalla
}
contexto= c.getContext('2d');//Muy importante especificar el contexto en el cual vamos a trabajar
function dibujar(){
contexto.fillStyle="rgba(0,0,0,0.05)";//Damos el color que tendra el recuadro en el que estara la animacion. en este caso sera transparente 0.05
contexto.fillRect(0,0,c.width,c.height);//Damos las dimensiones alto y ancho que tendra el cuadrado, que en este caso es de toda la pantalla
contexto.fillStyle= "#0f0";//Color de las letras
contexto.font= letraTam+"px arial";//Tama?o de la letra
for(var i=0;i<letras.length;i++){
text=Texto; //Le asigno el texto que definimos en la parte de arriba
//El ciclo for me permite darle las coordenadas correctas para posicionar el text x, y
text2=Texto2;//El texto dos que mostrara solo el 1
if(i%2==1){contexto.fillText(text,i*letraTam, letras[i]*letraTam);//Para imprimir texto disponesmos de fillText(texto,x,y)
}else{
contexto.fillText(text2,i*letraTam, letras[i]*letraTam);//Para imprimir texto disponesmos de fillText(texto,x,y)
}
if(letras[i]*letraTam > c.height && Math.random()>0.975){
letras[i]=0;
}
letras[i]++;
}
}
setInterval(dibujar,120);//velocidad a la que se ejecuta la funcion en milisegundos
}
</script>
</BODY>
</HTML>
EOF
擴展: 解決無法顯示真實IP的問題
我們觀察 Web1 和 Web2 的 access日志,會發(fā)現(xiàn)
# 在 Web1 和 Web2 上分別執(zhí)行 tail /var/log/nginx/access.log

為了解決 Web1/Web2 訪問日志的顯示問題(無法獲取客戶端真實的IP地址)
回到 LB1 服務(wù)器上,找到配置文件
vi /etc/nginx/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
#################### 配置開始 ######################
upstream my_web_service {
server 192.168.88.101:80;
server 192.168.88.102:80;
}
#################### 配置結(jié)束 ######################
server {
listen 80;
listen [::]:80;
#################### 配置開始 ######################
server_name 192.168.88.100; # 替換為實際域名或 IP
location / {
proxy_pass http://my_web_service; # 將請求轉(zhuǎn)發(fā)到負載均衡組
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr; # 添加這兩行
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
#################### 配置結(jié)束 ######################
server_name _;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}/usr/sbin/nginx -s reload
Nginx 變量:
$remote_addr:Nginx 變量,表示直接連接到當前服務(wù)器的客戶端 IP。
X-Real-IP:記錄原始客戶端 IP,適用于單級代理場景。
X-Forwarded-For:記錄完整代理鏈,適用于多級代理和日志分析。
最佳實踐:兩者同時設(shè)置,兼顧簡單性和可追溯性。
在Web01和Web02服務(wù)器上,打開配置文件(默認就是配置好的),定制日志顯示格式
在Web01和Web02服務(wù)器上
# vi /etc/nginx/nginx.conf
...
http {
...
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
...
}
在Web01和Web02服務(wù)器上,分別重啟
# /usr/sbin/nginx -s reload在 Web1 上和web2 上,都驗證測試
tail -3 /var/log/nginx/access.log
驗證宿主機 IP
# 在宿主機(筆記本 Windows 電腦)上,執(zhí)行 ipconfig
分發(fā)請求關(guān)鍵字
backup關(guān)鍵字:其他的沒有backup標識的服務(wù)器都無響應(yīng),才分發(fā)到backup服務(wù)器。
# vim conf/nginx.conf
http {
...
upstream my_web_service {
server 192.168.88.101:80 backup; # 優(yōu)先訪問其他的服務(wù)器
server 192.168.88.103:80;
}
...
}down關(guān)鍵字:任何時候,請求都不分發(fā)給配置了down關(guān)鍵字的服務(wù)器
# vim conf/nginx.conf
http {
...
upstream my_web_service {
server 192.168.88.101:80;
server 192.168.88.103:80 down; # 下線了
}
...
}用的最多的還是backup,關(guān)鍵時刻起到熱備作用!
負載均衡的3種調(diào)度算法(請求規(guī)則)
Nginx 官方默認3種負載均衡的算法:
① Round-Robin RR輪詢(默認): 一次一個的來(理論上的,實際實驗可能會有間隔)
② Weight 權(quán)重: 權(quán)重高多分發(fā)一些,服務(wù)器硬件更好的設(shè)置權(quán)重更高一些
比如,當我們設(shè)置成 1:9,會發(fā)現(xiàn)大部分情況,都是訪問的 Web2
# vim conf/nginx.conf
http {
...
upstream my_web_service {
server 192.168.88.101:80 weight=4;
server 192.168.88.103:80 weight=6;
}
...
}③ IP_HASH:代表把同一個IP來源的請求分到到同一個后端服務(wù)器
# vim conf/nginx.conf
http {
...
upstream my_web_service {
ip_hash; # 加上這個 IP Hash 就可以
server 192.168.88.101:80;
server 192.168.88.103:80;
}
...
}小結(jié):
Round-Robin:rr輪詢算法,請求均分
weight:weight=8
ip_hash:淘寶、京東 => 同一個IP所有請求都由同一個服務(wù)器處理
Session共享解決方案(調(diào)度算法)
① http協(xié)議,http協(xié)議是一個無狀態(tài)協(xié)議,無法記錄用戶的瀏覽軌跡。
② cookie技術(shù),可以把用戶的信息記錄在瀏覽器的緩存中(緩存存在過期時間)
③ session技術(shù),可以把用戶的瀏覽軌跡保存在服務(wù)器端(默認為/tmp目錄)
驗證碼也是Session文件,其產(chǎn)生的驗證碼會保存在這個文件中。
模擬負載均衡與Session共享問題:
第一步:配置負載均衡(默認算法使用輪詢算法)
第二步:使用賬號密碼登錄功能,登錄后臺管理界面(admin,123456)
我們發(fā)現(xiàn)了一個問題,無論我們這么輸入這個驗證碼,始終提示驗證失敗,主要原因:由于使用輪詢算法,所以生成驗證碼時,相當于一次請求,驗證驗證碼時也是一次請求。兩次請求所在的服務(wù)器不同,所以最終驗證總是失敗。
解決辦法:想辦法讓同一個IP的請求,分發(fā)到同一個Web服務(wù)器。
第三步:使用IP_HASH算法,問題解決
# vim conf/nginx.conf
http {
...
upstream my_web_service { # 加上這個 IP Hash 就可以
ip_hash;
server 192.168.88.101:80;
server 192.168.88.103:80;
}
...
}注:其實Session共享的解決方案,非常多,不僅僅只有IP_HASH一種算法,還可以基于MySQL或Redis實現(xiàn)Session共享
到此這篇關(guān)于詳解Nginx負載均衡/反向代理/日志分析的文章就介紹到這了,更多相關(guān)nginx負載均衡、反向代理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Nginx中反向代理+負載均衡+服務(wù)器宕機解決辦法詳解
這篇文章主要介紹了Nginx中反向代理+負載均衡+服務(wù)器宕機解決辦法詳解,反向代理保證系統(tǒng)安全,不暴露服務(wù)器IP,利用nginx服務(wù)器,利用內(nèi)網(wǎng)ip進行訪問,避免出現(xiàn)攻擊服務(wù)器的情況,需要的朋友可以參考下2024-01-01
Debian系統(tǒng)下為PHP程序配置Nginx服務(wù)器的基本教程
這篇文章主要介紹了Debian系統(tǒng)下為PHP程序配置Nginx服務(wù)器的基本教程,這里使用到了FastCGI和php-fpm,需要的朋友可以參考下2015-12-12

