圖解Nginx,系統架構演變 + Nginx反向代理與負載均衡

2023-02-22 09:02:43

大家好,我是哪吒。

本系列為SpringCloud微服務系列,先從微服務的入口Nginx開始學習,讀哪吒程式設計,品技術人生。

一、系統架構演變

最開始接觸Java語言的時候,我寫的第一個專案是圖書管理系統,當時是用JSP+servlet寫的,感覺很吊的樣子,全班領先水平。


慢慢的變成了JSP+SSM架構。


到現在單體架構最流行的SpringBoot+Vue


但是,隨著業務量的不斷增大,你會發現,這些單體架構,已經無法滿足資料日益膨脹的今天,動不動就幾萬、幾十萬的QPS,我記得當初200QPS,我就覺得挺嚇人了。

為了解決效能問題,慢慢的微服務SpringCloud架構浮出水面,微服務的核心理念是將應用細粒化,將單一應用拆分成若干個小應用,每個小應用提供單一的業務功能,獨立部署,服務之間相互呼叫,降低程式耦合度,解決單臺伺服器宕機的問題。

微服務提供了:

  1. 高可用:當某個節點伺服器宕機後,可以迅速將流量轉移到其它節點;
  2. 高效能:多臺伺服器對外提供相同的服務,提升程式的吞吐量;
  3. 高擴充套件:當業務發生激增時,可以通過增加節點的方式,解決效能問題;

注:本章的重點是Nginx,微服務其它元件就不畫了。

二、什麼是Nginx?

Nginx是俄羅斯人Igor Sysoev編寫的一款高效能 HTTP 和反向代理伺服器。Nginx選擇了epoll和kqueue作為網路I/O 模型,在高連線並行的情況下,Nginx是Apache伺服器不錯的替代品,它能夠支援高達50000個並行連線數的響應,執行穩定,且記憶體、CPU等系統資源消耗非常低。

三、servername匹配規則

  1. 完整匹配
  2. 萬用字元匹配
  3. 正則匹配

正則匹配格式,必須以~開頭,比如server_name ~^www\d+\.nzbc\.com$;。如果沒有~開頭,則Nginx會判定為完整匹配,在邏輯上,需要新增^和$錨定符號。正則匹配格式中.為正則元字元,需要通過反斜線進行跳脫,如果正在表示式中包含{},需要用雙引號參照起來,避免報錯。

四、正向代理與反向代理

1、正向代理

正向代理伺服器一般位於使用者和伺服器之間,使用者通過正向代理伺服器存取應用伺服器獲取資源。

最常見的例子就是,我們存取一個外國網站,該網站無法在國內直接存取,但是可以通過代理伺服器存取,也就是說,使用者向正向代理伺服器傳送一個請求並指定目標,然後正向代理伺服器向目標伺服器(外國網站)轉交請求並將獲得的內容返回給使用者。

正向代理伺服器,代理的是使用者端,去和伺服器端互動。

2、反向代理

反向代理伺服器一般位於使用者和伺服器之間,使用者存取反向代理伺服器獲取應用伺服器資源,使用者不知道應用伺服器的地址,是由代理伺服器轉發的,有降低網路和伺服器的負載,提高存取效率的作用。

反向代理伺服器,代理的是伺服器端,去和使用者端互動。

Nginx就是一款高效能的反向代理伺服器。

3、LVS

先說結論,LVS解決了Nginx單機效能瓶頸的問題

LVS主要用於多伺服器負載均衡,工作在網路的第四層,可以實現高效能、高可用的伺服器叢集技術,採用同步請求轉發的策略。

LVS支援的並行量要比Nginx高,可以配合keepalived使用,將Nginx作為LVS的節點機器,因為Nginx在網路的第七層,功能上肯定強於LVS。

使用者通過Nginx存取應用伺服器,應用伺服器直接將資料返回給機房路由,返回時不走Nginx了,降低了Nginx的效能消耗。

五、負載均衡策略

1、輪詢

預設使用輪詢方式,逐一轉發存取,這種情況適合無狀態請求,對談無法保持,可以通過基於使用者端實現對談保持。

對談保持方式:

(1)基於session實現:

session用於儲存使用者端使用者資訊,一般不在伺服器儲存session,可以通過SpringSession將session儲存到一個Redis伺服器中,再次存取時,可以到Redis伺服器中獲取session,實現session共用。

(2)基於cookie實現,無狀態的對談保持方式

使用者端存取時,先到許可權校驗伺服器校驗許可權,生成一個cookie,並進行加密,只有伺服器能解密,使用者端沒密碼無法解密,使用者端攜帶此cookie再次存取應用伺服器,應用伺服器進行解密校驗,完成無狀態的對談保持。

2、權重

通過upstream進行權重的定義。

  1. weight:權重
  2. down:下線不用了
  3. backup:備用伺服器

修改組態檔後,需要通過systemctl reload nginx命令重啟Nginx。

nginx.conf設定如下

http{
	upstream httpnz {
		server 192.168.66.1 weight=1 down;
		server 192.168.66.2 weight=5 backup;
		server 192.168.66.3 weight=10;
	}
	server{
		listen 80;
		server_name nzbc;
		
		location / {
			proxy_pass http://httpnz;
		}
	
		error_page 500.html;
		location = /500.html{
			root html;
		}
	}
}

3、ip_hash

每個請求按存取ip的hash結果分配,對映到固定某一臺的伺服器,會導致負載均衡不平衡。

當此應用伺服器宕機後,session會丟失,再次發起請求時,會重新固定存取另一臺正常的應用伺服器,並實現對談保持。

4、least_conn

最少連線存取。

5、url_hash

根據存取的url轉發請求,定向流量轉發。

每個請求按存取url的hash結果分配,對映到固定的某一臺伺服器,對談無法保持。

一般在獲取本地資源時使用(且本地資源不在同一臺伺服器上),比如通過地址1獲取圖片資源、通過地址2獲取pdf協定資源。

6、fair

根據伺服器響應時間轉發請求。

7、小結

最常用的負載均衡策略是設定權重,其它的形式,不是很常用。

ip_hash、least_conn、url_hash、fair,這幾種形式無法實現動態Nginx上下線(新增或減少Nginx伺服器),而且還會造成流量傾斜的問題,如果瞬時流量比較爆炸的時候,會將某個伺服器直接幹蹦

六、動靜分離

動靜分離的最終目的是將獲取靜態資源和動態資源分離開,提升伺服器效能和高可用性。

設定靜態資源,nginx.conf設定如下

http{
	upstream httpnz {
		server 192.168.66.1 weight=1 down;
		server 192.168.66.2 weight=5 backup;
		server 192.168.66.3 weight=10;
	}
	server{
		listen 80;
		server_name nzbc;
		
		location / {
			proxy_pass http://httpnz;
		}
		
		location ~*/(js/img/css) {
			root html;
			index index.html index.htm;
		}
		
		error_page 500 502 503 504 /50x.html;
		location = /50x.html{
			root html;
		}
	}
}

七、URLRewrite

URLRewrite是實現URL重寫的關鍵指令,根據regex (正規表示式)部分內容,進行重定向。

flag標記說明:

  1. break,本條匹配完成後即終止;
  2. last,本條匹配完成後,繼續向下匹配;
  3. redirect,返回302臨時重定向;
  4. permanent,返回301永久重定向;

設定URLRewrite,nginx.conf設定如下

http{
	upstream httpnz {
		server 192.168.66.1 weight=1 down;
		server 192.168.66.2 weight=5 backup;
		server 192.168.66.3 weight=10;
	}
	server{
		listen 80;
		server_name nzbc;
		
		location / {
			rewrite ^/([0-9]+).html$ /index.jsp?pageNum=$1 break;
			proxy_pass http://httpnz;
		}
		
		location ~*/(js/img/css) {
			root html;
			index index.html index.htm;
		}
		
		error_page 500 502 503 504 /50x.html;
		location = /50x.html{
			root html;
		}
	}
}