今天來和大家聊聊Nginx在我們實際應(yīng)運用中的一些非常有用的點。 早期的業(yè)務(wù)都是基于單體節(jié)點部署,由于前期訪問流量不大,因此單體結(jié)構(gòu)也可滿足需求,但隨著業(yè)務(wù)增長,流量也越來越大,那么最終單臺服務(wù)器受到的訪問壓力也會逐步增高。時間一長,單臺服務(wù)器性能無法跟上業(yè)務(wù)增長,就會造成線上頻繁宕機的現(xiàn)象發(fā)生,最終導(dǎo)致系統(tǒng)癱瘓無法繼續(xù)處理用戶的請求。 從上面的描述中,主要存在兩個問題: ①單體結(jié)構(gòu)的部署方式無法承載日益增長的業(yè)務(wù)流量。 ②當后端節(jié)點宕機后,整個系統(tǒng)會陷入癱瘓,導(dǎo)致整個項目不可用。 因此在這種背景下,引入負載均衡技術(shù)可帶來的收益: OK~,既然引入負載均衡技術(shù)可給我們帶來如此巨大的好處,那么又有那些方案可供選擇呢?主要有兩種負載方案,「「硬件層面與軟件層面」」 ,比較常用的硬件負載器有 Java開發(fā)者在線刷題神器 先來看看 原本客戶端是直接請求目標服務(wù)器,由目標服務(wù)器直接完成請求處理工作,但加入 了解了 ?首先創(chuàng)建 登錄后復(fù)制 ?下載 登錄后復(fù)制 沒有 登錄后復(fù)制 ?解壓 登錄后復(fù)制 ?下載并安裝 登錄后復(fù)制 也可以通過 登錄后復(fù)制 執(zhí)行完成后,然后 緊接著通過 登錄后復(fù)制 ?進入解壓后的 登錄后復(fù)制 ?編譯并安裝 登錄后復(fù)制 ?最后回到前面的 ?修改安裝后生成的 登錄后復(fù)制 ?制定配置文件并啟動 登錄后復(fù)制 登錄后復(fù)制 ?開放 登錄后復(fù)制 ?在 最終看到如上的 首先通過 登錄后復(fù)制 在該 前端的 登錄后復(fù)制 從上可以看出其邏輯并不復(fù)雜,僅是從響應(yīng)中獲取了 OK~,前提工作準備就緒后,再簡單修改一下 登錄后復(fù)制 至此,所有的前提工作準備就緒,緊接著再啟動 最終來看看效果: 負載均衡效果-動圖演示 因為配置了請求分發(fā)的權(quán)重, Java開發(fā)者在線刷題神器 客戶端發(fā)出的請求 請求分發(fā)原理 動靜分離應(yīng)該是聽的次數(shù)較多的性能優(yōu)化方案,那先思考一個問題:「「為什么需要做動靜分離呢?它帶來的好處是什么?」」 其實這個問題也并不難回答,當你搞懂了網(wǎng)站的本質(zhì)后,自然就理解了動靜分離的重要性。先來以淘寶為例分析看看: 淘寶首頁 當瀏覽器輸入 IDEA 工程結(jié)構(gòu) 在項目上線部署時,這些靜態(tài)資源會一起打成包,那此時思考一個問題:「「假設(shè)淘寶也是這樣干的,那么首頁加載時的請求最終會去到哪兒被處理?」」 答案毋庸置疑,首頁 但此時不妨分析看看,首頁 既然有這么多請求屬于靜態(tài)的,這些資源大概率情況下,長時間也不會出現(xiàn)變動,那為何還要讓這些請求到后端再處理呢?能不能在此之前就提前處理掉?當然 OK~,搞清楚動靜分離的必要性之后,如何實現(xiàn)動靜分離呢?其實非常簡單,實戰(zhàn)看看。 ①先在部署 登錄后復(fù)制 ②將項目中所有的靜態(tài)資源全部拷貝到該目錄下,而后將項目中的靜態(tài)資源移除重新打包。 ③稍微修改一下 登錄后復(fù)制 然后照常啟動 其中 移除后效果動圖 最后解讀一下那條location規(guī)則: 登錄后復(fù)制 綜上所述,簡單一句話概述:該配置表示匹配以 「最后提一嘴,也可以將靜態(tài)資源上傳到文件服務(wù)器中,然后location中配置一個新的upstream指向。」 Java開發(fā)者在線刷題神器 建立在動靜分離的基礎(chǔ)之上,如果一個靜態(tài)資源的 在 了解了 登錄后復(fù)制 在上述的壓縮配置中,最后一個 OK~,簡單修改好了 登錄后復(fù)制 分別來對比下壓縮前后的區(qū)別: 從圖中可以很明顯看出,未開啟壓縮機制前訪問時, 注意點:①對于圖片、視頻類型的數(shù)據(jù),會默認開啟壓縮機制,因此一般無需再次開啟壓縮。②對于 先來思考一個問題,接入 其實也就類似電腦的內(nèi)存跟不上 非緩沖參數(shù)項: 具體的 登錄后復(fù)制 上述的緩沖區(qū)參數(shù),是基于每個請求分配的空間,而并不是所有請求的共享空間。當然,具體的參數(shù)值還需要根據(jù)業(yè)務(wù)去決定,要綜合考慮機器的內(nèi)存以及每個請求的平均數(shù)據(jù)大小。 最后提一嘴:使用緩沖也可以減少即時傳輸帶來的帶寬消耗。 對于性能優(yōu)化而言,緩存是一種能夠大幅度提升性能的方案,因此幾乎可以在各處都能看見緩存,如客戶端緩存、代理緩存、服務(wù)器緩存等等, 那么在 「proxy_cache_path」:代理緩存的路徑。 語法: 登錄后復(fù)制 是的,你沒有看錯,就是這么長….,解釋一下每個參數(shù)項的含義: 「proxy_cache」:開啟或關(guān)閉代理緩存,開啟時需要指定一個共享內(nèi)存區(qū)域。 語法: 登錄后復(fù)制 zone為內(nèi)存區(qū)域的名稱,即上面中keys_zone設(shè)置的名稱。 「proxy_cache_key」:定義如何生成緩存的鍵。 語法: 登錄后復(fù)制 string為生成Key的規(guī)則,如 「proxy_cache_valid」:緩存生效的狀態(tài)碼與過期時間。 語法: 登錄后復(fù)制 code為狀態(tài)碼,time為有效時間,可以根據(jù)狀態(tài)碼設(shè)置不同的緩存時間。 例如: 「proxy_cache_min_uses」:設(shè)置資源被請求多少次后被緩存。 語法: 登錄后復(fù)制 number為次數(shù),默認為1。 「proxy_cache_use_stale」:當后端出現(xiàn)異常時,是否允許Nginx返回緩存作為響應(yīng)。 語法: 登錄后復(fù)制 error為錯誤類型,可配置 「proxy_cache_lock」:對于相同的請求,是否開啟鎖機制,只允許一個請求發(fā)往后端。 語法: 登錄后復(fù)制 「proxy_cache_lock_timeout」:配置鎖超時機制,超出規(guī)定時間后會釋放請求。 登錄后復(fù)制 「proxy_cache_methods」:設(shè)置對于那些HTTP方法開啟緩存。 語法: 登錄后復(fù)制 method為請求方法類型,如GET、HEAD等。 「proxy_no_cache」:定義不存儲緩存的條件,符合時不會保存。 語法: 登錄后復(fù)制 string為條件,例如 「proxy_cache_bypass」:定義不讀取緩存的條件,符合時不會從緩存中讀取。 語法: 登錄后復(fù)制 和上面 「add_header」:往響應(yīng)頭中添加字段信息。 語法: 登錄后復(fù)制 「$upstream_cache_status」:記錄了緩存是否命中的信息,存在多種情況: PS:這個和之前的不同,之前的都是參數(shù)項,這個是一個Nginx內(nèi)置變量。 OK~,對于 登錄后復(fù)制 接著來看一下效果,如下: 第一次訪問時,因為還沒有請求過資源,所以緩存中沒有數(shù)據(jù),因此沒有命中緩存。第二、三次,依舊沒有命中緩存,直至第四次時才顯示命中,這是為什么呢?因為在前面的緩存配置中,我們配置了加入緩存的最低條件為:「「資源至少要被請求三次以上才會加入緩存。」」 這樣可以避免很多無效緩存占用空間。 當緩存過多時,如果不及時清理會導(dǎo)致磁盤空間被“吃光”,因此我們需要一套完善的緩存清理機制去刪除緩存,在之前的 不過天無絕人之路,我們可以通過強大的第三方模塊 登錄后復(fù)制 ②通過 登錄后復(fù)制 ③再次去到之前 登錄后復(fù)制 ④重新構(gòu)建一次 登錄后復(fù)制 ⑤重新根據(jù)剛剛構(gòu)建的 登錄后復(fù)制 ⑥刪除之前 登錄后復(fù)制 ⑦從生成的 登錄后復(fù)制 至此,第三方緩存清除模塊 登錄后復(fù)制 然后再重啟 有時候往往有些需求,可能某些接口只能開放給對應(yīng)的合作商,或者購買/接入 登錄后復(fù)制 要同時屏蔽/開放多個 登錄后復(fù)制 分別將要禁止/開放的 登錄后復(fù)制 對于文件具體在哪兒導(dǎo)入,這個也并非隨意的,如果要整站屏蔽/開放就在 當然,上述只是最簡單的 跨域問題在之前的單體架構(gòu)開發(fā)中,其實是比較少見的問題,除非是需要接入第三方 產(chǎn)生跨域問題的主要原因就在于 「同源策略」 ,為了保證用戶信息安全,防止惡意網(wǎng)站竊取數(shù)據(jù),同源策略是必須的,否則 同源策略主要是指三點相同,「「協(xié)議+域名+端口」」 相同的兩個請求,則可以被看做是同源的,但如果其中任意一點存在不同,則代表是兩個不同源的請求,同源策略會限制了不同源之間的資源交互。 弄明白了跨域問題的產(chǎn)生原因,接下來看看 登錄后復(fù)制 在 但如果后端是采用分布式架構(gòu)開發(fā)的,有時候RPC調(diào)用也需要解決跨域問題,不然也同樣會出現(xiàn)無法跨域請求的異常,因此可以在你的后端項目中,通過繼承 首先了解一下何謂盜鏈:「「盜鏈即是指外部網(wǎng)站引入當前網(wǎng)站的資源對外展示」」 ,來舉個簡單的例子理解: 好比壁紙網(wǎng)站 那么如果我們自己是這個 登錄后復(fù)制 簡單了解語法后,接下來的實現(xiàn)如下: 登錄后復(fù)制 根據(jù)上述中的內(nèi)容配置后,就已經(jīng)通過 PS:防盜鏈機制也無法解決爬蟲偽造 在某些業(yè)務(wù)場景中需要傳輸一些大文件,但大文件傳輸時往往都會會出現(xiàn)一些 在傳輸大文件時, 上述配置僅是作為代理層需要配置的,因為最終客戶端傳輸文件還是直接與后端進行交互,這里只是把作為網(wǎng)關(guān)層的 隨著越來越多的網(wǎng)站接入 ①先去CA機構(gòu)或從云控制臺中申請對應(yīng)的 ②下載數(shù)字證書后,完整的文件總共有三個: ③在 ④最后修改一下 登錄后復(fù)制 OK~,根據(jù)如上配置了 線上如果采用單個節(jié)點的方式部署 接下來則會通過 ①首先創(chuàng)建一個對應(yīng)的目錄并下載 登錄后復(fù)制 ②進入解壓后的 登錄后復(fù)制 ③進入安裝目錄的 登錄后復(fù)制 ④編輯主機的 登錄后復(fù)制 ⑤克隆一臺之前的虛擬機作為從(備)機,編輯從機的 登錄后復(fù)制 ⑥新建 登錄后復(fù)制 ⑦編寫的腳本文件需要更改編碼格式,并賦予執(zhí)行權(quán)限,否則可能執(zhí)行失敗: 登錄后復(fù)制 ⑧由于安裝 登錄后復(fù)制 ⑨將 登錄后復(fù)制 其他命令: 登錄后復(fù)制 ⑩最后測試一下 登錄后復(fù)制 虛擬IP-VIP 從上圖中可以明顯看見虛擬 Ping-VIP 外部通過 經(jīng)過上述步驟后, 由于前面沒有域名的原因,因此最初 登錄后復(fù)制 最后來實驗一下效果: 在上述過程中,首先分別啟動了 從這個過程中不難發(fā)現(xiàn), 在上述過程中,我們通過手動關(guān)閉 現(xiàn)在再切換到另外一臺機器: 此刻我們會發(fā)現(xiàn),在主機 「「最終,利用Keepalived對Nginx做了主從熱備之后,無論是遇到線上宕機還是機房斷電等各類故障時,都能夠確保應(yīng)用系統(tǒng)能夠為用戶提供7×24小時服務(wù)。」」 到這里文章的篇幅較長了,最后再來聊一下關(guān)于 通常Nginx作為代理服務(wù),負責分發(fā)客戶端的請求,那么建議開啟 登錄后復(fù)制 零拷貝這個概念,在大多數(shù)性能較為不錯的中間件中都有出現(xiàn),例如 登錄后復(fù)制 零拷貝讀取機制與傳統(tǒng)資源讀取機制的區(qū)別: 從上述這個過程對比,很輕易就能看出兩者之間的性能區(qū)別。 在 登錄后復(fù)制 因此你的項目屬于交互性很強的應(yīng)用,那么可以手動開啟 相反,有些項目的業(yè)務(wù)對數(shù)據(jù)的實時性要求并不高,追求的則是更高的吞吐,那么則可以開啟 當然若一定時間后(一般為 注意:① 登錄后復(fù)制 工作進程的數(shù)量最高開到 同時也可以稍微調(diào)整一下每個工作進程能夠打開的文件句柄數(shù): 登錄后復(fù)制 操作系統(tǒng)內(nèi)核( 對于并發(fā)編程較為熟悉的伙伴都知道,因為進程/線程數(shù)往往都會遠超出系統(tǒng)CPU的核心數(shù),因為操作系統(tǒng)執(zhí)行的原理本質(zhì)上是采用時間片切換機制,也就是一個CPU核心會在多個進程之間不斷頻繁切換,造成很大的性能損耗。 而CPU親和機制則是指將每個 登錄后復(fù)制 在最開始就提到過: 登錄后復(fù)制 這里對于 至此,
A10、F5
等,但這些機器動輒大幾萬乃至幾十萬的成本,因此一般大型企業(yè)會采用該方案,如銀行、國企、央企等。而成本有限,但依舊想做負載均衡的項目,那么可在軟件層面實現(xiàn),如典型的Nginx
等,軟件層的負載也是本文的重點,畢竟Boss
們的準則之一就是:「「能靠技術(shù)實現(xiàn)的就盡量不花錢。」」一、性能怪獸-Nginx概念深入淺出
Nginx
是目前負載均衡技術(shù)中的主流方案,幾乎絕大部分項目都會使用它,Nginx
是一個輕量級的高性能HTTP
反向代理服務(wù)器,同時它也是一個通用類型的代理服務(wù)器,支持絕大部分協(xié)議,如TCP、UDP、SMTP、HTTPS
等。Nginx
與Redis相同,都是基于多路復(fù)用模型構(gòu)建出的產(chǎn)物,因此它與Redis
同樣具備 「「資源占用少、并發(fā)支持高」」 的特點,在理論上單節(jié)點的Nginx
同時支持5W
并發(fā)連接,而實際生產(chǎn)環(huán)境中,硬件基礎(chǔ)到位再結(jié)合簡單調(diào)優(yōu)后確實能達到該數(shù)值。Nginx
引入前后,客戶端請求處理流程的對比:Nginx
后,所有的請求會先經(jīng)過Nginx
,再由其進行分發(fā)到具體的服務(wù)器處理,處理完成后再返回Nginx
,最后由Nginx
將最終的響應(yīng)結(jié)果返回給客戶端。Nginx
的基本概念后,再來快速搭建一下環(huán)境,以及了解一些Nginx
的高級特性,如動靜分離、資源壓縮、緩存配置、IP
黑名單、高可用保障等。二、Nginx環(huán)境搭建
Nginx
的目錄并進入:[root@localhost]# mkdir /soft && mkdir /soft/nginx/
[root@localhost]# cd /soft/nginx/
Nginx
的安裝包,可以通過FTP
工具上傳離線環(huán)境包,也可通過wget
命令在線獲取安裝包:[root@localhost]# wget https://nginx.org/download/nginx-1.21.6.tar.gz
wget
命令的可通過yum
命令安裝:[root@localhost]# yum -y install wget
Nginx
的壓縮包:[root@localhost]# tar -xvzf nginx-1.21.6.tar.gz
Nginx
所需的依賴庫和包:[root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ gcc-c++
[root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ pcre pcre-devel4
[root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ zlib zlib-devel
[root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ openssl openssl-devel
yum
命令一鍵下載(推薦上面哪種方式):[root@localhost]# yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel
ls
查看目錄文件,會看一大堆依賴:rpm
命令依次將依賴包一個個構(gòu)建,或者通過如下指令一鍵安裝所有依賴包:[root@localhost]# rpm -ivh --nodeps *.rpm
nginx
目錄,然后執(zhí)行Nginx
的配置腳本,為后續(xù)的安裝提前配置好環(huán)境,默認位于/usr/local/nginx/
目錄下(可自定義目錄):[root@localhost]# cd nginx-1.21.6
[root@localhost]# ./configure --prefix=/soft/nginx/
Nginx
:[root@localhost]# make && make install
/soft/nginx/
目錄,輸入ls
即可看見安裝nginx
完成后生成的文件。conf
目錄下的nginx.conf
配置文件:[root@localhost]# vi conf/nginx.conf
修改端口號:listen 80;
修改IP地址:server_name 你當前機器的本地IP(線上配置域名);
Nginx
:[root@localhost]# sbin/nginx -c conf/nginx.conf
[root@localhost]# ps aux | grep nginx
Nginx
其他操作命令:sbin/nginx -t -c conf/nginx.conf # 檢測配置文件是否正常
sbin/nginx -s reload -c conf/nginx.conf # 修改配置后平滑重啟
sbin/nginx -s quit # 優(yōu)雅關(guān)閉Nginx,會在執(zhí)行完當前的任務(wù)后再退出
sbin/nginx -s stop # 強制終止Nginx,不管當前是否有任務(wù)在執(zhí)行
80
端口,并更新防火墻:[root@localhost]# firewall-cmd --zone=public --add-port=80/tcp --permanent
[root@localhost]# firewall-cmd --reload
[root@localhost]# firewall-cmd --zone=public --list-ports
Windows/Mac
的瀏覽器中,直接輸入剛剛配置的IP
地址訪問Nginx
:Nginx
歡迎界面,代表Nginx
安裝完成。三、Nginx反向代理-負載均衡
SpringBoot+Freemarker
快速搭建一個WEB
項目:springboot-web-nginx,然后在該項目中,創(chuàng)建一個IndexNginxController.java
文件,邏輯如下:@Controller
public class IndexNginxController {
@Value("${server.port}")
private String port;
@RequestMapping("/")
public ModelAndView index(){
ModelAndView model = new ModelAndView();
model.addObject("port", port);
model.setViewName("index");
return model;
}
}
Controller
類中,存在一個成員變量:port
,它的值即是從application.properties
配置文件中獲取server.port
值。當出現(xiàn)訪問/
資源的請求時,跳轉(zhuǎn)前端index
頁面,并將該值攜帶返回。index.ftl
文件代碼如下:<html>
<head>
<title>Nginx演示頁面</title>
<link href="nginx_style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div style="border: 2px solid red;margin: auto;width: 800px;text-align: center">
<div id="nginx_title">
<h1>歡迎來到熊貓高級會所,我是竹子${port}號!</h1>
</div>
</div>
</body>
</html>
port
輸出。nginx.conf
的配置即可:upstream nginx_boot{
# 30s內(nèi)檢查心跳發(fā)送兩次包,未回復(fù)就代表該機器宕機,請求分發(fā)權(quán)重比為1:2
server 192.168.0.000:8080 weight=100 max_fails=2 fail_timeout=30s;
server 192.168.0.000:8090 weight=200 max_fails=2 fail_timeout=30s;
# 這里的IP請配置成你WEB服務(wù)所在的機器IP
}
server {
location / {
root html;
# 配置一下index的地址,最后加上index.ftl。
index index.html index.htm index.jsp index.ftl;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 請求交給名為nginx_boot的upstream上
proxy_pass http://nginx_boot;
}
}
Nginx
,然后再啟動兩個web
服務(wù),第一個WEB
服務(wù)啟動時,在application.properties
配置文件中,將端口號改為8080
,第二個WEB
服務(wù)啟動時,將其端口號改為8090
。8080、8090
的權(quán)重比為2:1
,因此請求會根據(jù)權(quán)重比均攤到每臺機器,也就是8080
一次、8090
兩次、8080
一次……Nginx請求分發(fā)原理
192.168.12.129
最終會轉(zhuǎn)變?yōu)椋?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;, Consolas, Monaco, Menlo, monospace">http://192.168.12.129:80/,然后再向目標IP
發(fā)起請求,流程如下:
Nginx
監(jiān)聽了192.168.12.129
的80
端口,所以最終該請求會找到Nginx
進程;Nginx
首先會根據(jù)配置的location
規(guī)則進行匹配,根據(jù)客戶端的請求路徑/
,會定位到location /{}
規(guī)則;location
中配置的proxy_pass
會再找到名為nginx_boot
的upstream
;upstream
中的配置信息,將請求轉(zhuǎn)發(fā)到運行WEB
服務(wù)的機器處理,由于配置了多個WEB
服務(wù),且配置了權(quán)重值,因此Nginx
會依次根據(jù)權(quán)重比分發(fā)請求。四、Nginx動靜分離
www.taobao.com
訪問淘寶首頁時,打開開發(fā)者調(diào)試工具可以很明顯的看到,首頁加載會出現(xiàn)100+
的請求數(shù),而正常項目開發(fā)時,靜態(tài)資源一般會放入到resources/static/
目錄下:100+
的所有請求都會來到部署WEB
服務(wù)的機器處理,那則代表著一個客戶端請求淘寶首頁,就會對后端服務(wù)器造成100+
的并發(fā)請求。毫無疑問,這對于后端服務(wù)器的壓力是尤為巨大的。100+
的請求中,是不是至少有60+
是屬于*.js、*.css、*.html、*.jpg.....
這類靜態(tài)資源的請求呢?答案是Yes
。OK
,因此經(jīng)過分析之后能夠明確一點:「「做了動靜分離之后,至少能夠讓后端服務(wù)減少一半以上的并發(fā)量。」」 到此時大家應(yīng)該明白了動靜分離能夠帶來的性能收益究竟有多大。
Nginx
的機器,Nginx
目錄下創(chuàng)建一個目錄static_resources
:mkdir static_resources
nginx.conf
的配置,增加一條location
匹配規(guī)則:location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css){
root /soft/nginx/static_resources;
expires 7d;
}
nginx
和移除了靜態(tài)資源的WEB
服務(wù),你會發(fā)現(xiàn)原本的樣式、js
效果、圖片等依舊有效,如下:static
目錄下的nginx_style.css
文件已被移除,但效果依舊存在(綠色字體+藍色大邊框):location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)
~
代表匹配時區(qū)分大小寫.*
代表任意字符都可以出現(xiàn)零次或多次,即資源名不限制\.
代表匹配后綴分隔符.(html|...|css)
代表匹配括號里所有靜態(tài)資源類型.html~.css
為后綴的所有資源請求。五、Nginx資源壓縮
Size
越小,那么自然傳輸速度會更快,同時也會更節(jié)省帶寬,因此我們在部署項目時,也可以通過Nginx
對于靜態(tài)資源實現(xiàn)壓縮傳輸,一方面可以節(jié)省帶寬資源,第二方面也可以加快響應(yīng)速度并提升系統(tǒng)整體吞吐。Nginx
也提供了三個支持資源壓縮的模塊ngx_http_gzip_module、ngx_http_gzip_static_module、ngx_http_gunzip_module
,其中ngx_http_gzip_module
屬于內(nèi)置模塊,代表著可以直接使用該模塊下的一些壓縮指令,后續(xù)的資源壓縮操作都基于該模塊,先來看看壓縮配置的一些參數(shù)/指令:Nginx
中的基本壓縮配置后,接下來可以在Nginx
中簡單配置一下:http{
# 開啟壓縮機制
gzip on;
# 指定會被壓縮的文件類型(也可自己配置其他類型)
gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/gif image/png;
# 設(shè)置壓縮級別,越高資源消耗越大,但壓縮效果越好
gzip_comp_level 5;
# 在頭部中添加Vary: Accept-Encoding(建議開啟)
gzip_vary on;
# 處理壓縮請求的緩沖區(qū)數(shù)量和大小
gzip_buffers 16 8k;
# 對于不支持壓縮功能的客戶端請求不開啟壓縮機制
gzip_disable "MSIE [1-6]\."; # 低版本的IE瀏覽器不支持壓縮
# 設(shè)置壓縮響應(yīng)所支持的HTTP最低版本
gzip_http_version 1.1;
# 設(shè)置觸發(fā)壓縮的最小閾值
gzip_min_length 2k;
# 關(guān)閉對后端服務(wù)器的響應(yīng)結(jié)果進行壓縮
gzip_proxied off;
}
gzip_proxied
選項,可以根據(jù)系統(tǒng)的實際情況決定,總共存在多種選項:
off
:關(guān)閉Nginx
對后臺服務(wù)器的響應(yīng)結(jié)果進行壓縮。expired
:如果響應(yīng)頭中包含Expires
信息,則開啟壓縮。no-cache
:如果響應(yīng)頭中包含Cache-Control:no-cache
信息,則開啟壓縮。no-store
:如果響應(yīng)頭中包含Cache-Control:no-store
信息,則開啟壓縮。private
:如果響應(yīng)頭中包含Cache-Control:private
信息,則開啟壓縮。no_last_modified
:如果響應(yīng)頭中不包含Last-Modified
信息,則開啟壓縮。no_etag
:如果響應(yīng)頭中不包含ETag
信息,則開啟壓縮。auth
:如果響應(yīng)頭中包含Authorization
信息,則開啟壓縮。any
:無條件對后端的響應(yīng)結(jié)果開啟壓縮機制。Nginx
的壓縮配置后,可以在原本的index
頁面中引入一個jquery-3.6.0.js
文件:<script type="text/javascript" src="jquery-3.6.0.js"></script>
js
文件的原始大小為230K
,當配置好壓縮后再重啟Nginx
,會發(fā)現(xiàn)文件大小從230KB→69KB
,效果立竿見影!.js
文件而言,需要指定壓縮類型為application/javascript
,而并非text/javascript、application/x-javascript
。六、Nginx緩沖區(qū)
Nginx
的項目一般請求流程為:“客戶端→Nginx
→服務(wù)端”,在這個過程中存在兩個連接:“客戶端→Nginx
、Nginx
→服務(wù)端”,那么兩個不同的連接速度不一致,就會影響用戶的體驗(比如瀏覽器的加載速度跟不上服務(wù)端的響應(yīng)速度)。CPU
速度,所以對于用戶造成的體驗感極差,因此在CPU
設(shè)計時都會加入三級高速緩沖區(qū),用于緩解CPU
和內(nèi)存速率不一致的矛盾。在Nginx
也同樣存在緩沖區(qū)的機制,主要目的就在于:「「用來解決兩個連接之間速度不匹配造成的問題」」 ,有了緩沖后,Nginx
代理可暫存后端的響應(yīng),然后按需供給數(shù)據(jù)給客戶端。先來看看一些關(guān)于緩沖區(qū)的配置項:
proxy_buffering
:是否啟用緩沖機制,默認為on
關(guān)閉狀態(tài)。client_body_buffer_size
:設(shè)置緩沖客戶端請求數(shù)據(jù)的內(nèi)存大小。proxy_buffers
:為每個請求/連接設(shè)置緩沖區(qū)的數(shù)量和大小,默認4 4k/8k
。proxy_buffer_size
:設(shè)置用于存儲響應(yīng)頭的緩沖區(qū)大小。proxy_busy_buffers_size
:在后端數(shù)據(jù)沒有完全接收完成時,Nginx
可以將busy
狀態(tài)的緩沖返回給客戶端,該參數(shù)用來設(shè)置busy
狀態(tài)的buffer
具體有多大,默認為proxy_buffer_size*2
。proxy_temp_path
:當內(nèi)存緩沖區(qū)存滿時,可以將數(shù)據(jù)臨時存放到磁盤,該參數(shù)是設(shè)置存儲緩沖數(shù)據(jù)的目錄。path
是臨時目錄的路徑。
proxy_temp_path path;
path是臨時目錄的路徑proxy_temp_file_write_size
:設(shè)置每次寫數(shù)據(jù)到臨時文件的大小限制。proxy_max_temp_file_size
:設(shè)置臨時的緩沖目錄中允許存儲的最大容量。
proxy_connect_timeout
:設(shè)置與后端服務(wù)器建立連接時的超時時間。proxy_read_timeout
:設(shè)置從后端服務(wù)器讀取響應(yīng)數(shù)據(jù)的超時時間。proxy_send_timeout
:設(shè)置向后端服務(wù)器傳輸請求數(shù)據(jù)的超時時間。nginx.conf
配置如下:http{
proxy_connect_timeout 10;
proxy_read_timeout 120;
proxy_send_timeout 10;
proxy_buffering on;
client_body_buffer_size 512k;
proxy_buffers 4 64k;
proxy_buffer_size 16k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
proxy_temp_path /soft/nginx/temp_buffer;
}
七、Nginx緩存機制
Nginx
的緩存則屬于代理緩存的一種。對于整個系統(tǒng)而言,加入緩存帶來的優(yōu)勢額外明顯:
Nginx
中,又該如何配置代理緩存呢?先來看看緩存相關(guān)的配置項:proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
path
:緩存的路徑地址。levels
:緩存存儲的層次結(jié)構(gòu),最多允許三層目錄。use_temp_path
:是否使用臨時目錄。keys_zone
:指定一個共享內(nèi)存空間來存儲熱點Key(1M可存儲8000個Key)。inactive
:設(shè)置緩存多長時間未被訪問后刪除(默認是十分鐘)。max_size
:允許緩存的最大存儲空間,超出后會基于LRU算法移除緩存,Nginx會創(chuàng)建一個Cache manager的進程移除數(shù)據(jù),也可以通過purge方式。manager_files
:manager進程每次移除緩存文件數(shù)量的上限。manager_sleep
:manager進程每次移除緩存文件的時間上限。manager_threshold
:manager進程每次移除緩存后的間隔時間。loader_files
:重啟Nginx載入緩存時,每次加載的個數(shù),默認100。loader_sleep
:每次載入時,允許的最大時間上限,默認200ms。loader_threshold
:一次載入后,停頓的時間間隔,默認50ms。purger
:是否開啟purge方式移除數(shù)據(jù)。purger_files
:每次移除緩存文件時的數(shù)量。purger_sleep
:每次移除時,允許消耗的最大時間。purger_threshold
:每次移除完成后,停頓的間隔時間。proxy_cache zone | off;
proxy_cache_key string;
$scheme$proxy_host$request_uri
。proxy_cache_valid [code ...] time;
proxy_cache_valid 200 302 30m;
proxy_cache_min_uses number;
proxy_cache_use_stale error;
timeout|invalid_header|updating|http_500...
。proxy_cache_lock on | off;
proxy_cache_lock_timeout time;
proxy_cache_methods method;
proxy_no_cache string...;
$cookie_nocache $arg_nocache $arg_comment;
proxy_cache_bypass string...;
proxy_no_cache
的配置方法類似。add_header fieldName fieldValue;
MISS
:請求未命中緩存。HIT
:請求命中緩存。EXPIRED
:請求命中緩存但緩存已過期。STALE
:請求命中了陳舊緩存。REVALIDDATED
:Nginx驗證陳舊緩存依然有效。UPDATING
:命中的緩存內(nèi)容陳舊,但正在更新緩存。BYPASS
:響應(yīng)結(jié)果是從原始服務(wù)器獲取的。
Nginx
中的緩存配置項大概了解后,接著來配置一下Nginx
代理緩存:http{
# 設(shè)置緩存的目錄,并且內(nèi)存中緩存區(qū)名為hot_cache,大小為128m,
# 三天未被訪問過的緩存自動清楚,磁盤中緩存的最大容量為2GB。
proxy_cache_path /soft/nginx/cache levels=1:2 keys_zone=hot_cache:128m inactive=3d max_size=2g;
server{
location / {
# 使用名為nginx_cache的緩存空間
proxy_cache hot_cache;
# 對于200、206、304、301、302狀態(tài)碼的數(shù)據(jù)緩存1天
proxy_cache_valid 200 206 304 301 302 1d;
# 對于其他狀態(tài)的數(shù)據(jù)緩存30分鐘
proxy_cache_valid any 30m;
# 定義生成緩存鍵的規(guī)則(請求的url+參數(shù)作為key)
proxy_cache_key $host$uri$is_args$args;
# 資源至少被重復(fù)訪問三次后再加入緩存
proxy_cache_min_uses 3;
# 出現(xiàn)重復(fù)請求時,只讓一個去后端讀數(shù)據(jù),其他的從緩存中讀取
proxy_cache_lock on;
# 上面的鎖超時時間為3s,超過3s未獲取數(shù)據(jù),其他請求直接去后端
proxy_cache_lock_timeout 3s;
# 對于請求參數(shù)或cookie中聲明了不緩存的數(shù)據(jù),不再加入緩存
proxy_no_cache $cookie_nocache $arg_nocache $arg_comment;
# 在響應(yīng)頭中添加一個緩存是否命中的狀態(tài)(便于調(diào)試)
add_header Cache-status $upstream_cache_status;
}
}
}
緩存清理
proxy_cache_path
參數(shù)中有purger
相關(guān)的選項,開啟后可以幫我們自動清理緩存,但遺憾的是:**purger
系列參數(shù)只有商業(yè)版的NginxPlus
才能使用,因此需要付費才可使用。**ngx_cache_purge
來替代,先來安裝一下該插件:①首先去到Nginx
的安裝目錄下,創(chuàng)建一個cache_purge
目錄:[root@localhost]# mkdir cache_purge && cd cache_purge
wget
指令從github
上拉取安裝包的壓縮文件并解壓:[root@localhost]# wget https://github.com/FRiCKLE/ngx_cache_purge/archive/2.3.tar.gz
[root@localhost]# tar -xvzf 2.3.tar.gz
Nginx
的解壓目錄下:[root@localhost]# cd /soft/nginx/nginx1.21.6
Nginx
,通過--add-module
的指令添加剛剛的第三方模塊:[root@localhost]# ./configure --prefix=/soft/nginx/ --add-module=/soft/nginx/cache_purge/ngx_cache_purge-2.3/
Nginx
,再次編譯一下,「但切記不要make install」 :[root@localhost]# make
Nginx
的啟動文件,不放心的也可以移動到其他位置:[root@localhost]# rm -rf /soft/nginx/sbin/nginx
objs
目錄中,重新復(fù)制一個Nginx
的啟動文件到原來的位置:[root@localhost]# cp objs/nginx /soft/nginx/sbin/nginx
ngx_cache_purge
就安裝完成了,接下來稍微修改一下nginx.conf
配置,再添加一條location
規(guī)則:location ~ /purge(/.*) {
# 配置可以執(zhí)行清除操作的IP(線上可以配置成內(nèi)網(wǎng)機器)
# allow 127.0.0.1; # 代表本機
allow all; # 代表允許任意IP清除緩存
proxy_cache_purge $host$1$is_args$args;
}
Nginx
,接下來即可通過http://xxx/purge/xx
的方式清除緩存。八、Nginx實現(xiàn)IP黑白名單
API
的合作伙伴,那么此時就需要實現(xiàn)類似于IP
白名單的功能。而有時候有些惡意攻擊者或爬蟲程序,被識別后需要禁止其再次訪問網(wǎng)站,因此也需要實現(xiàn)IP
黑名單。那么這些功能無需交由后端實現(xiàn),可直接在Nginx
中處理。Nginx
做黑白名單機制,主要是通過allow、deny
配置項來實現(xiàn):allow xxx.xxx.xxx.xxx; # 允許指定的IP訪問,可以用于實現(xiàn)白名單。
deny xxx.xxx.xxx.xxx; # 禁止指定的IP訪問,可以用于實現(xiàn)黑名單。
IP
訪問時,如果所有IP
全部寫在nginx.conf
文件中定然是不顯示的,這種方式比較冗余,那么可以新建兩個文件BlocksIP.conf、WhiteIP.conf
:# --------黑名單:BlocksIP.conf---------
deny 192.177.12.222; # 屏蔽192.177.12.222訪問
deny 192.177.44.201; # 屏蔽192.177.44.201訪問
deny 127.0.0.0/8; # 屏蔽127.0.0.1到127.255.255.254網(wǎng)段中的所有IP訪問
# --------白名單:WhiteIP.conf---------
allow 192.177.12.222; # 允許192.177.12.222訪問
allow 192.177.44.201; # 允許192.177.44.201訪問
allow 127.45.0.0/16; # 允許127.45.0.1到127.45.255.254網(wǎng)段中的所有IP訪問
deny all; # 除開上述IP外,其他IP全部禁止訪問
IP
添加到對應(yīng)的文件后,可以再將這兩個文件在nginx.conf
中導(dǎo)入:http{
# 屏蔽該文件中的所有IP
include /soft/nginx/IP/BlocksIP.conf;
server{
location xxx {
# 某一系列接口只開放給白名單中的IP
include /soft/nginx/IP/blockip.conf;
}
}
}
http
中導(dǎo)入,如果只需要一個域名下屏蔽/開放就在sever
中導(dǎo)入,如果只需要針對于某一系列接口屏蔽/開放IP
,那么就在location
中導(dǎo)入。IP
黑/白名單實現(xiàn)方式,同時也可以通過ngx_http_geo_module、ngx_http_geo_module
第三方庫去實現(xiàn)(這種方式可以按地區(qū)、國家進行屏蔽,并且提供了IP
庫)。九、Nginx跨域配置
SDK
時,才需要處理此問題。但隨著現(xiàn)在前后端分離、分布式架構(gòu)的流行,跨域問題也成為了每個Java開發(fā)必須要懂得解決的一個問題。跨域問題產(chǎn)生的原因
cookie
可以共享。由于http
無狀態(tài)協(xié)議通常會借助cookie
來實現(xiàn)有狀態(tài)的信息記錄,例如用戶的身份/密碼等,因此一旦cookie
被共享,那么會導(dǎo)致用戶的身份信息被盜取。Nginx解決跨域問題
Nginx
中又該如何解決跨域呢?其實比較簡單,在nginx.conf
中稍微添加一點配置即可:location / {
# 允許跨域的請求,可以自定義變量$http_origin,*表示所有
add_header 'Access-Control-Allow-Origin' *;
# 允許攜帶cookie請求
add_header 'Access-Control-Allow-Credentials' 'true';
# 允許跨域請求的方法:GET,POST,OPTIONS,PUT
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT';
# 允許請求時攜帶的頭部信息,*表示所有
add_header 'Access-Control-Allow-Headers' *;
# 允許發(fā)送按段獲取資源的請求
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
# 一定要有!!!否則Post請求無法進行跨域!
# 在發(fā)送Post跨域請求前,會以O(shè)ptions方式發(fā)送預(yù)檢請求,服務(wù)器接受時才會正式請求
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
# 對于Options方式的請求返回204,表示接受跨域請求
return 204;
}
}
nginx.conf
文件加上如上配置后,跨域請求即可生效了。HandlerInterceptorAdapter
類、實現(xiàn)WebMvcConfigurer
接口、添加@CrossOrgin
注解的方式實現(xiàn)接口之間的跨域配置。十、Nginx防盜鏈設(shè)計
X
站、Y
站,X
站是一點點去購買版權(quán)、簽約作者的方式,從而積累了海量的壁紙素材,但Y
站由于資金等各方面的原因,就直接通過<img src="X站/xxx.jpg" />
這種方式照搬了X
站的所有壁紙資源,繼而提供給用戶下載。X
站的Boss
,心中必然不爽,那么此時又該如何屏蔽這類問題呢?那么接下來要敘說的「「防盜鏈」」 登場了!Nginx
的防盜鏈機制實現(xiàn),跟一個頭部字段:Referer
有關(guān),該字段主要描述了當前請求是從哪兒發(fā)出的,那么在Nginx
中就可獲取該值,然后判斷是否為本站的資源引用請求,如果不是則不允許訪問。Nginx
中存在一個配置項為valid_referers
,正好可以滿足前面的需求,語法如下:valid_referers none | blocked | server_names | string ...;
none
:表示接受沒有Referer
字段的HTTP
請求訪問。blocked
:表示允許http://
或https//
以外的請求訪問。server_names
:資源的白名單,這里可以指定允許訪問的域名。string
:可自定義字符串,支配通配符、正則表達式寫法。# 在動靜分離的location中開啟防盜鏈機制
location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css){
# 最后面的值在上線前可配置為允許的域名地址
valid_referers blocked 192.168.12.129;
if ($invalid_referer) {
# 可以配置成返回一張禁止盜取的圖片
# rewrite ^/ http://xx.xx.com/NO.jpg;
# 也可直接返回403
return 403;
}
root /soft/nginx/static_resources;
expires 7d;
}
Nginx
實現(xiàn)了最基本的防盜鏈機制,最后只需要額外重啟一下就好啦!當然,對于防盜鏈機制實現(xiàn)這塊,也有專門的第三方模塊ngx_http_accesskey_module
實現(xiàn)了更為完善的設(shè)計,感興趣的小伙伴可以自行去看看。
referers
信息的這種方式抓取數(shù)據(jù)。十一、Nginx大文件傳輸配置
Bug
,比如文件超出限制、文件傳輸過程中請求超時等,那么此時就可以在Nginx
稍微做一些配置,先來了解一些關(guān)于大文件傳輸時可能會用的配置項:client_max_body_size
、client_header_timeout
、proxy_read_timeout
、proxy_send_timeout
這四個參數(shù)值都可以根據(jù)自己項目的實際情況來配置。Nginx
配置調(diào)高一點,調(diào)到能夠“容納大文件”傳輸?shù)某潭取.斎唬?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;, Consolas, Monaco, Menlo, monospace">Nginx中也可以作為文件服務(wù)器使用,但需要用到一個專門的第三方模塊nginx-upload-module
,如果項目中文件上傳的作用處不多,那么建議可以通過Nginx
搭建,畢竟可以節(jié)省一臺文件服務(wù)器資源。但如若文件上傳/下載較為頻繁,那么還是建議額外搭建文件服務(wù)器,并將上傳/下載功能交由后端處理。十二、Nginx配置SLL證書
HTTPS
,因此Nginx
中僅配置HTTP
還不夠,往往還需要監(jiān)聽443
端口的請求,HTTPS
為了確保通信安全,所以服務(wù)端需配置對應(yīng)的數(shù)字證書,當項目使用Nginx
作為網(wǎng)關(guān)時,那么證書在Nginx
中也需要配置,接下來簡單聊一下關(guān)于SSL
證書配置過程:SSL
證書,審核通過后下載Nginx
版本的證書。.crt、.key、.pem
:
.crt
:數(shù)字證書文件,.crt
是.pem
的拓展文件,因此有些人下載后可能沒有。.key
:服務(wù)器的私鑰文件,及非對稱加密的私鑰,用于解密公鑰傳輸?shù)臄?shù)據(jù)。.pem
:Base64-encoded
編碼格式的源證書文本文件,可自行根需求修改拓展名。Nginx
目錄下新建certificate
目錄,并將下載好的證書/私鑰等文件上傳至該目錄。nginx.conf
文件即可,如下:# ----------HTTPS配置-----------
server {
# 監(jiān)聽HTTPS默認的443端口
listen 443;
# 配置自己項目的域名
server_name www.xxx.com;
# 打開SSL加密傳輸
ssl on;
# 輸入域名后,首頁文件所在的目錄
root html;
# 配置首頁的文件名
index index.html index.htm index.jsp index.ftl;
# 配置自己下載的數(shù)字證書
ssl_certificate certificate/xxx.pem;
# 配置自己下載的服務(wù)器私鑰
ssl_certificate_key certificate/xxx.key;
# 停止通信時,加密會話的有效期,在該時間段內(nèi)不需要重新交換密鑰
ssl_session_timeout 5m;
# TLS握手時,服務(wù)器采用的密碼套件
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
# 服務(wù)器支持的TLS版本
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# 開啟由服務(wù)器決定采用的密碼套件
ssl_prefer_server_ciphers on;
location / {
....
}
}
# ---------HTTP請求轉(zhuǎn)HTTPS-------------
server {
# 監(jiān)聽HTTP默認的80端口
listen 80;
# 如果80端口出現(xiàn)訪問該域名的請求
server_name www.xxx.com;
# 將請求改寫為HTTPS(這里寫你配置了HTTPS的域名)
rewrite ^(.*)$ https://www.xxx.com;
}
Nginx
后,你的網(wǎng)站即可通過https://
的方式訪問,并且當客戶端使用http://
的方式訪問時,會自動將其改寫為HTTPS
請求。十三、Nginx的高可用
Nginx
,難免會出現(xiàn)天災(zāi)人禍,比如系統(tǒng)異常、程序宕機、服務(wù)器斷電、機房爆炸、地球毀滅….哈哈哈,夸張了。但實際生產(chǎn)環(huán)境中確實存在隱患問題,由于Nginx
作為整個系統(tǒng)的網(wǎng)關(guān)層接入外部流量,所以一旦Nginx
宕機,最終就會導(dǎo)致整個系統(tǒng)不可用,這無疑對于用戶的體驗感是極差的,因此也得保障Nginx
高可用的特性。keepalived
的VIP
機制,實現(xiàn)Nginx
的高可用。VIP
并不是只會員的意思,而是指Virtual IP
,即虛擬IP
。keepalived
在之前單體架構(gòu)開發(fā)時,是一個用的較為頻繁的高可用技術(shù),比如MySQL、Redis、MQ、Proxy、Tomcat
等各處都會通過keepalived
提供的VIP
機制,實現(xiàn)單節(jié)點應(yīng)用的高可用。Keepalived+重啟腳本+雙機熱備搭建
keepalived
到Linux
中并解壓:[root@localhost]# mkdir /soft/keepalived && cd /soft/keepalived
[root@localhost]# wget https://www.keepalived.org/software/keepalived-2.2.4.tar.gz
[root@localhost]# tar -zxvf keepalived-2.2.4.tar.gz
keepalived
目錄并構(gòu)建安裝環(huán)境,然后編譯并安裝:[root@localhost]# cd keepalived-2.2.4
[root@localhost]# ./configure --prefix=/soft/keepalived/
[root@localhost]# make && make install
/soft/keepalived/etc/keepalived/
并編輯配置文件:[root@localhost]# cd /soft/keepalived/etc/keepalived/
[root@localhost]# vi keepalived.conf
keepalived.conf
核心配置文件,如下:global_defs {
# 自帶的郵件提醒服務(wù),建議用獨立的監(jiān)控或第三方SMTP,也可選擇配置郵件發(fā)送。
notification_email {
root@localhost
}
notification_email_from root@localhost
smtp_server localhost
smtp_connect_timeout 30
# 高可用集群主機身份標識(集群中主機身份標識名稱不能重復(fù),建議配置成本機IP)
router_id 192.168.12.129
}
# 定時運行的腳本文件配置
vrrp_script check_nginx_pid_restart {
# 之前編寫的nginx重啟腳本的所在位置
script "/soft/scripts/keepalived/check_nginx_pid_restart.sh"
# 每間隔3秒執(zhí)行一次
interval 3
# 如果腳本中的條件成立,重啟一次則權(quán)重-20
weight -20
}
# 定義虛擬路由,VI_1為虛擬路由的標示符(可自定義名稱)
vrrp_instance VI_1 {
# 當前節(jié)點的身份標識:用來決定主從(MASTER為主機,BACKUP為從機)
state MASTER
# 綁定虛擬IP的網(wǎng)絡(luò)接口,根據(jù)自己的機器的網(wǎng)卡配置
interface ens33
# 虛擬路由的ID號,主從兩個節(jié)點設(shè)置必須一樣
virtual_router_id 121
# 填寫本機IP
mcast_src_ip 192.168.12.129
# 節(jié)點權(quán)重優(yōu)先級,主節(jié)點要比從節(jié)點優(yōu)先級高
priority 100
# 優(yōu)先級高的設(shè)置nopreempt,解決異常恢復(fù)后再次搶占造成的腦裂問題
nopreempt
# 組播信息發(fā)送間隔,兩個節(jié)點設(shè)置必須一樣,默認1s(類似于心跳檢測)
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
# 將track_script塊加入instance配置塊
track_script {
# 執(zhí)行Nginx監(jiān)控的腳本
check_nginx_pid_restart
}
virtual_ipaddress {
# 虛擬IP(VIP),也可擴展,可配置多個。
192.168.12.111
}
}
keepalived.conf
文件,如下:global_defs {
# 自帶的郵件提醒服務(wù),建議用獨立的監(jiān)控或第三方SMTP,也可選擇配置郵件發(fā)送。
notification_email {
root@localhost
}
notification_email_from root@localhost
smtp_server localhost
smtp_connect_timeout 30
# 高可用集群主機身份標識(集群中主機身份標識名稱不能重復(fù),建議配置成本機IP)
router_id 192.168.12.130
}
# 定時運行的腳本文件配置
vrrp_script check_nginx_pid_restart {
# 之前編寫的nginx重啟腳本的所在位置
script "/soft/scripts/keepalived/check_nginx_pid_restart.sh"
# 每間隔3秒執(zhí)行一次
interval 3
# 如果腳本中的條件成立,重啟一次則權(quán)重-20
weight -20
}
# 定義虛擬路由,VI_1為虛擬路由的標示符(可自定義名稱)
vrrp_instance VI_1 {
# 當前節(jié)點的身份標識:用來決定主從(MASTER為主機,BACKUP為從機)
state BACKUP
# 綁定虛擬IP的網(wǎng)絡(luò)接口,根據(jù)自己的機器的網(wǎng)卡配置
interface ens33
# 虛擬路由的ID號,主從兩個節(jié)點設(shè)置必須一樣
virtual_router_id 121
# 填寫本機IP
mcast_src_ip 192.168.12.130
# 節(jié)點權(quán)重優(yōu)先級,主節(jié)點要比從節(jié)點優(yōu)先級高
priority 90
# 優(yōu)先級高的設(shè)置nopreempt,解決異常恢復(fù)后再次搶占造成的腦裂問題
nopreempt
# 組播信息發(fā)送間隔,兩個節(jié)點設(shè)置必須一樣,默認1s(類似于心跳檢測)
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
# 將track_script塊加入instance配置塊
track_script {
# 執(zhí)行Nginx監(jiān)控的腳本
check_nginx_pid_restart
}
virtual_ipaddress {
# 虛擬IP(VIP),也可擴展,可配置多個。
192.168.12.111
}
}
scripts
目錄并編寫Nginx
的重啟腳本,check_nginx_pid_restart.sh
:[root@localhost]# mkdir /soft/scripts /soft/scripts/keepalived
[root@localhost]# touch /soft/scripts/keepalived/check_nginx_pid_restart.sh
[root@localhost]# vi /soft/scripts/keepalived/check_nginx_pid_restart.sh
#!/bin/sh
# 通過ps指令查詢后臺的nginx進程數(shù),并將其保存在變量nginx_number中
nginx_number=`ps -C nginx --no-header | wc -l`
# 判斷后臺是否還有Nginx進程在運行
if [ $nginx_number -eq 0 ];then
# 如果后臺查詢不到`Nginx`進程存在,則執(zhí)行重啟指令
/soft/nginx/sbin/nginx -c /soft/nginx/conf/nginx.conf
# 重啟后等待1s后,再次查詢后臺進程數(shù)
sleep 1
# 如果重啟后依舊無法查詢到nginx進程
if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then
# 將keepalived主機下線,將虛擬IP漂移給從機,從機上線接管Nginx服務(wù)
systemctl stop keepalived.service
fi
fi
[root@localhost]# vi /soft/scripts/keepalived/check_nginx_pid_restart.sh
:set fileformat=unix # 在vi命令里面執(zhí)行,修改編碼格式
:set ff # 查看修改后的編碼格式
[root@localhost]# chmod +x /soft/scripts/keepalived/check_nginx_pid_restart.sh
keepalived
時,是自定義的安裝位置,因此需要拷貝一些文件到系統(tǒng)目錄中:[root@localhost]# mkdir /etc/keepalived/
[root@localhost]# cp /soft/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
[root@localhost]# cp /soft/keepalived/keepalived-2.2.4/keepalived/etc/init.d/keepalived /etc/init.d/
[root@localhost]# cp /soft/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
keepalived
加入系統(tǒng)服務(wù)并設(shè)置開啟自啟動,然后測試啟動是否正常:[root@localhost]# chkconfig keepalived on
[root@localhost]# systemctl daemon-reload
[root@localhost]# systemctl enable keepalived.service
[root@localhost]# systemctl start keepalived.service
systemctl disable keepalived.service # 禁止開機自動啟動
systemctl restart keepalived.service # 重啟keepalived
systemctl stop keepalived.service # 停止keepalived
tail -f /var/log/messages # 查看keepalived運行時日志
VIP
是否生效,通過查看本機是否成功掛載虛擬IP
:[root@localhost]# ip addr
IP
已經(jīng)成功掛載,但另外一臺機器192.168.12.130
并不會掛載這個虛擬IP
,只有當主機下線后,作為從機的192.168.12.130
才會上線,接替VIP
。最后測試一下外網(wǎng)是否可以正常與VIP
通信,即在Windows
中直接ping VIP
:VIP
通信時,也可以正常Ping
通,代表虛擬IP
配置成功。Nginx高可用性測試
keepalived
的VIP
機制已經(jīng)搭建成功,在上個階段中主要做了幾件事:
Nginx
的機器掛載了VIP
。keepalived
搭建了主從雙機熱備。keepalived
實現(xiàn)了Nginx
宕機重啟。server_name
配置的是當前機器的IP
,所以需稍微更改一下nginx.conf
的配置:sever{
listen 80;
# 這里從機器的本地IP改為虛擬IP
server_name 192.168.12.111;
# 如果這里配置的是域名,那么則將域名的映射配置改為虛擬IP
}
keepalived、nginx
服務(wù),然后通過手動停止nginx
的方式模擬了Nginx
宕機情況,過了片刻后再次查詢后臺進程,我們會發(fā)現(xiàn)nginx
依舊存活。keepalived
已經(jīng)為我們實現(xiàn)了Nginx
宕機后自動重啟的功能,那么接著再模擬一下服務(wù)器出現(xiàn)故障時的情況:keepalived
服務(wù)模擬了機器斷電、硬件損壞等情況(因為機器斷電等情況=主機中的keepalived
進程消失),然后再次查詢了一下本機的IP
信息,很明顯會看到VIP
消失了!192.168.12.130
來看看情況:192.168.12.129
宕機后,VIP自動從主機飄移到了從機192.168.12.130
上,而此時客戶端的請求就最終會來到130
這臺機器的Nginx
上。十四、Nginx性能優(yōu)化
Nginx
的性能優(yōu)化,主要就簡單說說收益最高的幾個優(yōu)化項,在這塊就不再展開敘述了,畢竟影響性能都有多方面原因?qū)е碌模热缇W(wǎng)絡(luò)、服務(wù)器硬件、操作系統(tǒng)、后端服務(wù)、程序自身、數(shù)據(jù)庫服務(wù)等。優(yōu)化一:打開長連接配置
HTTP
長連接,用戶減少握手的次數(shù),降低服務(wù)器損耗,具體如下:upstream xxx {
# 長連接數(shù)
keepalive 32;
# 每個長連接提供的最大請求數(shù)
keepalived_requests 100;
# 每個長連接沒有新的請求時,保持的最長時間
keepalive_timeout 60s;
}
優(yōu)化二、開啟零拷貝技術(shù)
Kafka、Netty
等,而Nginx
中也可以配置數(shù)據(jù)零拷貝技術(shù),如下:sendfile on; # 開啟零拷貝機制
優(yōu)化三、開啟無延遲或多包共發(fā)機制
Nginx
中有兩個較為關(guān)鍵的性能參數(shù),即tcp_nodelay、tcp_nopush
,開啟方式如下:tcp_nodelay on;
tcp_nopush on;
TCP/IP
協(xié)議中默認是采用了Nagle算法的,即在網(wǎng)絡(luò)數(shù)據(jù)傳輸過程中,每個數(shù)據(jù)報文并不會立馬發(fā)送出去,而是會等待一段時間,將后面的幾個數(shù)據(jù)包一起組合成一個數(shù)據(jù)報文發(fā)送,但這個算法雖然提高了網(wǎng)絡(luò)吞吐量,但是實時性卻降低了。tcp_nodelay
配置,讓應(yīng)用程序向內(nèi)核遞交的每個數(shù)據(jù)包都會立即發(fā)送出去。但這樣會產(chǎn)生大量的TCP
報文頭,增加很大的網(wǎng)絡(luò)開銷。tcp_nopush
配置項,這個配置就類似于“塞子”的意思,首先將連接塞住,使得數(shù)據(jù)先不發(fā)出去,等到拔去塞子后再發(fā)出去。設(shè)置該選項后,內(nèi)核會盡量把小數(shù)據(jù)包拼接成一個大的數(shù)據(jù)包(一個MTU
)再發(fā)送出去.200ms
),內(nèi)核仍然沒有積累到一個MTU
的量時,也必須發(fā)送現(xiàn)有的數(shù)據(jù),否則會一直阻塞。tcp_nodelay、tcp_nopush
兩個參數(shù)是“互斥”的,如果追求響應(yīng)速度的應(yīng)用推薦開啟tcp_nodelay
參數(shù),如IM
、金融等類型的項目。如果追求吞吐量的應(yīng)用則建議開啟tcp_nopush
參數(shù),如調(diào)度系統(tǒng)、報表系統(tǒng)等。tcp_nodelay
一般要建立在開啟了長連接模式的情況下使用。②tcp_nopush
參數(shù)是必須要開啟sendfile
參數(shù)才可使用的。優(yōu)化四、調(diào)整Worker工作進程
Nginx
啟動后默認只會開啟一個Worker
工作進程處理客戶端請求,而我們可以根據(jù)機器的CPU核數(shù)開啟對應(yīng)數(shù)量的工作進程,以此來提升整體的并發(fā)量支持,如下:# 自動根據(jù)CPU核心數(shù)調(diào)整Worker進程數(shù)量
worker_processes auto;
8
個就OK了,8
個之后就不會有再大的性能提升。# 每個Worker能打開的文件描述符,最少調(diào)整至1W以上,負荷較高建議2-3W
worker_rlimit_nofile 20000;
kernel
)都是利用文件描述符來訪問文件,無論是打開、新建、讀取、寫入文件時,都需要使用文件描述符來指定待操作的文件,因此該值越大,代表一個進程能夠操作的文件越多(但不能超出內(nèi)核限制,最多建議3.8W
左右為上限)。優(yōu)化五、開啟CPU親和機制
Nginx
的工作進程,綁定在固定的CPU核心上,從而減小CPU切換帶來的時間開銷和資源損耗,開啟方式如下:worker_cpu_affinity auto;
優(yōu)化六、開啟epoll模型及調(diào)整并發(fā)連接數(shù)
Nginx、Redis
都是基于多路復(fù)用模型去實現(xiàn)的程序,但最初版的多路復(fù)用模型select/poll
最大只能監(jiān)聽1024
個連接,而epoll
則屬于select/poll
接口的增強版,因此采用該模型能夠大程度上提升單個Worker
的性能,如下:events {
# 使用epoll網(wǎng)絡(luò)模型
use epoll;
# 調(diào)整每個Worker能夠處理的連接數(shù)上限
worker_connections 10240;
}
select/poll/epoll
模型就不展開細說了,后面的IO模型文章中會詳細剖析。十五、放在最后的結(jié)尾
Nginx
的大部分內(nèi)容都已闡述完畢,關(guān)于最后一小節(jié)的性能優(yōu)化內(nèi)容,其實在前面就談到的動靜分離、分配緩沖區(qū)、資源緩存、防盜鏈、資源壓縮等內(nèi)容,也都可歸納為性能優(yōu)化的方案。
以上就是14個Nginx的核心功能點,建議收藏!的詳細內(nèi)容,更多請關(guān)注www.92cms.cn其它相關(guān)文章!