天天看點

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

大家好,我是哪吒。

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

一、系統架構演變

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

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

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

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

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

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

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

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

微服務提供了:

  1. 高可用:當某個節點伺服器當機後,可以迅速将流量轉移到其它節點;
  2. 高性能:多台伺服器對外提供相同的服務,提升程式的吞吐量;
  3. 高擴充:當業務發生激增時,可以通過增加節點的方式,解決性能問題;
圖解Nginx,系統架構演變 + Nginx反向代理與負載均衡

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

二、什麼是Nginx?

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

三、servername比對規則

  1. 完整比對
  2. 通配符比對
  3. 正則比對

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

四、正向代理與反向代理

1、正向代理

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

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

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

2、反向代理

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

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

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

3、LVS

先說結論,。

LVS主要用于多伺服器負載均衡,工作在網絡的第四層,可以實作高性能、高可用的伺服器叢集技術,采用同步請求轉發的政策。

,将Nginx作為LVS的節點機器,因為Nginx在網絡的第七層,功能上肯定強于LVS。

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

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

五、負載均衡政策

1、輪詢

預設使用輪詢方式,逐一轉發通路,這種情況适合無狀态請求,會話無法保持,可以通過基于用戶端實作會話保持。

會話保持方式:

(1)基于session實作:

session用于存儲用戶端使用者資訊,一般不在伺服器存儲session,可以通過SpringSession将session存儲到一個Redis伺服器中,再次通路時,可以到Redis伺服器中擷取session,實作session共享。

(2)基于cookie實作,無狀态的會話保持方式:

用戶端通路時,先到權限校驗伺服器校驗權限,生成一個cookie,并進行加密,隻有伺服器能解密,用戶端沒密碼無法解密,用戶端攜帶此cookie再次通路應用伺服器,應用伺服器進行解密校驗,完成無狀态的會話保持。

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

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,系統架構演變 + Nginx反向代理與負載均衡

六、動靜分離

動靜分離的最終目的是将擷取靜态資源和動态資源分離開,提升伺服器性能和高可用性。

圖解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;
        }
    }
}           

繼續閱讀