「從單體架構(gòu)到分布式架構(gòu)」請求增多,單點變集群(2):Nginx

上一個章節(jié),我們學(xué)習(xí)了負(fù)載均衡的理論知識,那么是不是把應(yīng)用部署多套,前面掛一個負(fù)載均衡的軟件或硬件就可以應(yīng)對高并發(fā)了?其實還有很多問題需要考慮。比如:

1. 當(dāng)一臺服務(wù)器掛掉,請求如何轉(zhuǎn)發(fā)到其他正常的服務(wù)器上?

2. 掛掉的服務(wù)器,怎么才能不再訪問?

3. 如何保證負(fù)載均衡的高可用性?

等等等等...

讓我們帶著這些問題,實戰(zhàn)學(xué)習(xí)一下 Nginx 的配置和使用。

1. 前置概念

在正式介紹 Nginx 之前,首先讓我們先了解一下概念。

1. 中間件

干 IT 太累了,我準(zhǔn)備辭職開了個燒烤攤,賣羊肉串;

賣羊肉串首先就得有羊肉,于是我就聯(lián)系了很多養(yǎng)殖場,我又是一個比較負(fù)責(zé)任的人,為了保證羊肉的質(zhì)量,我就去考察了一家又一家養(yǎng)殖場,同時我也是個“小氣”的人,所以我考察過程中,和對方談判、比價,最終選了一個養(yǎng)殖場作為我的羊肉供應(yīng)商,為我提供羊肉。

經(jīng)營了一陣子,這個養(yǎng)殖場提供的羊肉質(zhì)量沒有以前好了,那么我就重新考察、談判、比價,如此反復(fù),我投入了大量的時間和精力。

于是我找到了一個信得過的代理公司,約定要羊肉的質(zhì)量和數(shù)量,談好價錢,以后我只找代理商拿貨,具體代理商找的哪家養(yǎng)殖場我不去過問,甚至代理商可以送貨上門。

在這個例子里面,賣燒烤就是業(yè)務(wù),我的燒烤攤是業(yè)務(wù)端,養(yǎng)殖場是底層,而?這個信得過的代理公司,就是中間件。

2. 正向代理和反向代理

正向代理:我住在北京,但是想回老家買套房,但是我沒辦法親自回老家考察,于是我就派我的管家回老家考察;管家就是正向代理服務(wù)器;正向代理服務(wù)器代表了客戶端,在正向代理的過程中,服務(wù)端只和代理服務(wù)器打交道(房東只和我的管家談),并不知道真正的客戶端是誰。

反向代理:我住在北京,但是想回老家買套房,但是我沒辦法親自回老家考察,于是我打個電話聯(lián)系了老家的房屋中介去辦這件事兒;房屋中介就是反向代理;這里的反向代理,代表的是房東,在反向代理的過程中,客戶端只和反向代理服務(wù)器打交道,并不知道真正的服務(wù)端是誰。

當(dāng)然,我的管家也可以聯(lián)系我老家的房屋中介,那么架構(gòu)圖就會變成:

2. Nginx 的概念

了解完上面的幾個概念,那么 Nginx 的概念理解起來就簡單很多了:

Nginx 就是一個開源的、高性能的、可靠的 Http 中間件;?它經(jīng)常被用作 Http 代理、反向代理、負(fù)載均衡等等,當(dāng)然它也能做正向代理,但是實際很少有這么用的。

3. 最簡單的 Nginx 使用示例

本章節(jié)項目的代碼:chapter3

Step 1. 部署多套環(huán)境

我們將章節(jié) 1 中的項目 chapter1 復(fù)制出來一份,改名為 chapter3,表示是第 3 章節(jié)的項目,同時修改:

1. pom.xml 中的 artifactId 修改為 chapter32. application.yml 中的 server.port 修改成 8089

這樣我們分別啟動 chapter1 和 chapter3,這樣就相當(dāng)于把相同的項目部署了兩套,端口分別是 8088 和 8089 。

Step 2. 下載 Nginx

我們可以在 Nginx 的官網(wǎng) 下載我們所需的版本,因為我使用 windows 環(huán)境開發(fā),所以我在這里就選擇了 nginx/Windows-1.14.2 這個版本。

下載完成解壓縮,不需要額外的安裝,可以直接使用。

Step 3. 配置 Nginx

進(jìn)入 nginx-1.14.2\conf 目錄下,用文本編輯器打開 nginx.conf,對配置文件進(jìn)行如下修改:

1. 在 http 中增加 upstream,并配置兩臺環(huán)境的地址;2. 在 http.server.location 中增加 proxy_pass 的配置;

http{

...

#增加upstream的配置,其中myserver是自己起的名字

upstreammyserver{

server127.0.0.1:8088;? #有幾套環(huán)境,就配置幾條

server127.0.0.1:8089;

}

server{

listen80;

server_namelocalhost;

#charsetkoi8-r;

#access_loglogs/host.access.logmain;

location/ {

roothtml;

indexindex.htmlindex.htm;

proxy_passhttp://myserver; #增加,其中 http://myserver 的 myserver 要和上文對應(yīng)

? ? ? ? }

? ? ? }

? ? }

? ? ...

}

完整配置文件請參考:nginx.conf

Step 4. 啟動 Nginx

我們可以直接雙擊 nginx-1.14.2 目錄下的 nginx.exe 啟動;也可以通過 cmd 命令打開控制臺,進(jìn)入 nginx-1.14.2 目錄執(zhí)行如下命令啟動 Nginx:

start nginx //啟動 Nginx ;啟動后可能一閃而過,我們可以看一下任務(wù)管理器是否有名字叫做 nginx.exe 的進(jìn)程

nginx.exe -s stop //停止 Nginx

nginx.exe -s quit //停止 Nginx

Step 5. 測試 Nginx

讓我們測試一下 Nginx 是否配置并啟動成功,打開瀏覽器輸入:

http://127.0.0.1/queryAdmin

注意這里并沒有加端口號,是因為 url 中沒有端口號的時候表示端口號為 80,而我們 Nginx 的配置文件中,監(jiān)聽的正是 80 端口 (listen 80);我們可以在瀏覽器中看到服務(wù)返回的結(jié)果:

User : Admin

這就說明 Nginx 已經(jīng)轉(zhuǎn)發(fā)了我們的請求到了服務(wù)端,并正確返回,那么負(fù)載均衡是如何體現(xiàn)的呢?讓我們多刷新幾次瀏覽器,然后看看后臺日志:

我前后一共調(diào)用了 5 次服務(wù),可以看到兩個服務(wù)端分別接收到了 2 次和 3 次請求,負(fù)載均衡達(dá)到了效果。

4. Nginx 常見的路由策略

1. 輪詢法

最簡單的輪詢法,多余的配置不需要增加。

upstreammyserver{

server127.0.0.1:8088;# 有幾套環(huán)境,就配置幾條

? server 127.0.0.1:8089;

}

2. 源地址哈希法

使用 ip_hash 關(guān)鍵字,每一個請求,都按 hash(IP) 的結(jié)果決定訪問哪臺服務(wù)器;

upstreammyserver{

ip_hash; #hash(IP)

server127.0.0.1:8088;? # 有幾套環(huán)境,就配置幾條

server127.0.0.1:8089;

}

如果我們本地測試,多次訪問接口,可以發(fā)現(xiàn)請求永遠(yuǎn)落到同一個服務(wù)上,因為本地 IP 一直沒有改變。

3. 加權(quán)輪詢法

使用 weight 關(guān)鍵字,設(shè)置每臺服務(wù)器的權(quán)重;

upstreammyserver{

server127.0.0.1:8088weight=1;# 20% 請求會發(fā)給8088

? server 127.0.0.1:8089 weight=4;

}

4. 最小連接數(shù)法

根據(jù)每個服務(wù)器節(jié)點的連接數(shù),動態(tài)地選擇當(dāng)前連接數(shù)最少的服務(wù)器轉(zhuǎn)發(fā)請求;

upstreammyserver{

least_conn;

server127.0.0.1:8088;

server127.0.0.1:8089;

}

5. 最快響應(yīng)速度法

根據(jù)每個服務(wù)器節(jié)點的響應(yīng)時間(請求的往返延遲),動態(tài)地選擇當(dāng)前響應(yīng)速度最快的服務(wù)器轉(zhuǎn)發(fā)請求;需要額外安裝 nginx-upstream-fair 模塊。

upstreammyserver{

fair; # 額外安裝nginx-upstream-fair模塊

server127.0.0.1:8088;

server127.0.0.1:8089;

}

6. URL 哈希算法

對 URL 進(jìn)行 Hash 運算,根據(jù)結(jié)果來分配請求,這樣每個 URL 都可以訪問到同一個服務(wù)端;當(dāng)服務(wù)端有緩存的時候,比較有效。

upstreammyserver{

hash$request_uri;

server127.0.0.1:8088;# 有幾套環(huán)境,就配置幾條

? server 127.0.0.1:8089;

}

也可以安裝第三方模塊,比如我們要使用 URL 一致性哈希算法,那么我們可以安裝

ngx_http_upstream_consistent_hash 模塊。

upstreammyserver{

consistent_hash$request_uri;

server127.0.0.1:8088;

server127.0.0.1:8089;

}

參考資料:Upstream Consistent Hash

5. Nginx 常用功能

5.1 請求失敗重試

當(dāng)一臺服務(wù)器掛掉,請求如何轉(zhuǎn)發(fā)到其他正常的服務(wù)器上?

我們可以先做個試驗,就是關(guān)閉 8089 端口的服務(wù),只保留 8088 端口的服務(wù),然后調(diào)用幾次接口,如果其中一次調(diào)用長時間不返回(瀏覽器訪問狀態(tài)圖標(biāo)一直在打轉(zhuǎn)),表示本次請求發(fā)送到了 8089 端口,那么讓我們等待一段時間...大約一分鐘之后,8080 端口服務(wù)的后臺日志,打印出來日志,調(diào)用端接收到了返回,這說明:

Nginx 默認(rèn)有失敗重試機(jī)制;

默認(rèn)的超時時間為 60s 。

這里的超時時間是可以修改的,需要在 http.server.location 中增加如下配置:

location/ {

roothtml;

indexindex.html index.htm;

proxy_passhttp://myserver;

proxy_connect_timeout5;# 連接超時時間

? ? ? ? ? ? proxy_send_timeout 5; # 發(fā)送數(shù)據(jù)給后端服務(wù)器的超時時間

? ? ? ? ? ? proxy_read_timeout 5; # 后端服務(wù)器的相應(yīng)時間

? ? ? ? ? ? #proxy_next_upstream off; # 是否要關(guān)閉重試機(jī)制

? ? ? ? }

完整配置文件請參考:設(shè)置超時重試時間5秒-nginx.conf

不過這里要注意一點,如果設(shè)置了服務(wù)器相應(yīng)超時時間(比如設(shè)置了 10s ),萬一應(yīng)用的業(yè)務(wù)處理時間比較慢(業(yè)務(wù)處理花費了 15s ),那么會導(dǎo)致 Nginx 超時重試,那么可能會造成重復(fù)處理。

5.2 后端服務(wù)器節(jié)點健康狀態(tài)檢查

如果掛掉一臺服務(wù)器,路由到這臺服務(wù)器請求每次都要等到超時時間過去,才能發(fā)起重試,如果 Nginx 不再把請求發(fā)送給掛掉的服務(wù)器,那就省事多了;

這就叫做“后端服務(wù)器節(jié)點健康狀態(tài)檢查”。

如果不安裝第三方模塊,可以做如下配置完成“后端服務(wù)器節(jié)點健康狀態(tài)檢查”:

1. 設(shè)置超時時間:

location/ {

roothtml;

indexindex.html index.htm;

proxy_passhttp://myserver;

proxy_connect_timeout5;# 連接超時時間

? ? ? ? ? ? proxy_send_timeout 5; # 發(fā)送數(shù)據(jù)給后端服務(wù)器的超時時間

? ? ? ? ? ? proxy_read_timeout 5; # 后端服務(wù)器的相應(yīng)時間

? ? ? ? ? ? #proxy_next_upstream off; # 是否要關(guān)閉重試機(jī)制

? ? ? ? }

2. 設(shè)置嘗試重試的次數(shù):

upstreammyserver{

server127.0.0.1:8088max_fails=1fail_timeout=100s;

server127.0.0.1:8089max_fails=1fail_timeout=100s;

}

其中 max_fails 表示最多失敗次數(shù),fail_timeout 表示在一個時間段內(nèi),服務(wù)器不會再次嘗試訪問;上面的配置表示在 100s 內(nèi),只要超時失敗 1 次,就不再訪問該服務(wù)器。

完整配置文件請參考:設(shè)置超時重試時間5s-失敗1次100秒之內(nèi)不再訪問-nginx.conf

除此之外,我們還可以安裝第三方模塊來實現(xiàn)“后端服務(wù)器節(jié)點健康狀態(tài)檢查”:

nginx_upstream_check_module

ngx_http_healthcheck_module

5.3 Nginx 的高可用

以為使用 Nginx ,部署了多臺應(yīng)用服務(wù)器,可以保證應(yīng)用服務(wù)器的高可用(掛掉一臺,還有其他服務(wù)器可以用);

但是如何保證負(fù)載均衡的高可用性?也就是萬一 Nginx 掛了怎么辦?

Nginx 同樣也需要部署多臺,架構(gòu)大概是這個樣子的:

現(xiàn)在應(yīng)用比較廣泛的是利用 keepalived 實現(xiàn) Nignx 的高可用:

5.4 其他

除了以上的常見功能,強(qiáng)大的 Nginx 還可以:

限制 IP 訪問頻率和帶寬占用;

緩存靜態(tài)資源;

文件壓縮;

TCP 負(fù)載;

防盜鏈;

等等等等...

總結(jié)

我們現(xiàn)在的架構(gòu)已經(jīng)變成了:

編輯不易,希望看到的小伙伴多多轉(zhuǎn)發(fā),收藏,給小編一個 關(guān)注!感謝您的閱讀,下面小編給大家準(zhǔn)備了一份(馬士兵大佬的視頻,面試資料技術(shù)文檔)進(jìn)大廠必備,免費送給大家!

如果你想成為一名優(yōu)秀的 Java 架構(gòu)師,那么這份手冊上的內(nèi)容幾乎是必須要掌握的。如果你想獲取這份學(xué)習(xí)資料的小伙伴,關(guān)注小編,轉(zhuǎn)發(fā),收藏文章,私信[高并發(fā)]即可獲得獲取方式!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容