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