天天看點

nginx 反向代理_了解Nginx的反向代理與負載均衡

點選上方☝Java程式設計技術樂園,輕松關注!及時擷取有趣有料的技術文章

文章很長,耐心閱讀,記得點贊和關注哦~
nginx 反向代理_了解Nginx的反向代理與負載均衡

Nginx 簡介

初次釋出

Nginx (engine x) 是一個高性能的HTTP和反向代理服務,也是一個IMAP/POP3/SMTP服務。Nginx是由伊戈爾·賽索耶夫為俄羅斯通路量第二的Rambler.ru站點(俄文:Рамблер)開發的,第一個公開版本0.1.0釋出于2004年10月4日。其将源代碼以類BSD許可證的形式釋出,因它的穩定性、豐富的功能集、示例配置檔案和低系統資源的消耗而聞名。

性能概覽

Nginx是一款輕量級的Web 伺服器/反向代理伺服器及電子郵件(IMAP/POP3)代理伺服器,并在一個BSD-like 協定下發行。其特點是占有記憶體少,并發能力強,Nginx的并發能力在同類型的網頁伺服器中表現較好。

與舊版本的Apache不同,Nginx不采用每客戶機一線程的設計模型,而是充分使用異步邏輯(這一點與NodeJS采取了相同的做法,支援高并發,Nginx在官方測試的結果中,能夠支援五萬個平行連接配接,而在實際的運作中,是可以支援二萬至四萬個平行連結),削減了上下文排程開銷,是以并發服務能力更強。整體采用子產品化設計,有豐富的子產品庫和第三方子產品庫,配置靈活。

Nginx的反向代理

了解反向代理

要使用Nginx的反向代理的特性,首先就是要了解什麼是反向代理,為此我們先從最簡單的C/S架構說起,C/S架構,也即是Client-Server的架構。而最簡單的C/S架構,也即是以單個節點作為後端Server的C/S架構。

C/S架構中的單點Server

在普通的開發當中,單點Server的服務方式非常常見,比如使用Django架構做背景服務的時候,就可以通過簡單的run server指令運作起一個臨時的服務,接着通過位址就可以通路到這個服務了。當然了,對于Django而言,run server指令隻是提供開發周期的調試使用的便捷工具,更一般的情況是通過uWSGI把這個Django服務跑起來,以擷取并比run server更好的服務性能。

此時部署整一個架構圖如下:

nginx 反向代理_了解Nginx的反向代理與負載均衡

對于請求量非常少的服務,這樣的部署不會有什麼問題,但如果這個服務請求量上來的時候,這樣部署的架構就很有問題了。

首先一個很客觀的問題就是,如果單從伺服器的實體特性來看,這個伺服器就不能支援這麼高的請求量。這種情況下,就迫使開發者去把服務遷移到一個CPU更強、記憶體更高,綜合性能更好的伺服器。通過更換伺服器當然可以解決這個問題,在不考慮成本的條件下,總可以找到性能更好的伺服器來替換原來的伺服器以支撐服務,但這種理想的條件不在本文考慮範圍之内。

第二個問題就是,如果服務Server單節點發生了故障,就必然會影響整個服務,因為對于衆多的Client用戶端都是連接配接的一個Server服務端,如果這個節點不可用了,勢必會影響所有使用了用戶端的使用者。

為了解決這兩個顯而易見的問題,就必須提出一種可以橫向拓展的部署架構,使得服務可以支撐的請求量可以随着服務的橫向拓展而增加。因而就催生了如下的部署架構:

nginx 反向代理_了解Nginx的反向代理與負載均衡

基于代理的可橫向拓展的C/S架構

在這個部署的架構當中,除了Server節點,還多出了一個叫“Proxy”的節點,那麼這個節點是幹嘛的呢?

“Proxy”的這個節點,它把他接收的所有的請求都轉發到他後面的Server節點當中,然後等待Server節點處理請求,再從Server節點取回執行結果傳回到Client。是以,“Proxy”的這個節點,他實際上不處理任何的請求。

我們先來看這樣子的架構怎麼解決了以上的問題,再來思考“Proxy”的這個角色。

首先是第一個問題,伺服器性能不足的問題,這個架構如何解決性能不足的問題呢?在這個架構裡面,假設Server節點S1性能到達瓶頸了,不能處理更多的請求了。如果采用上面的這個架構,那麼我們可以添加Server節點S2,同時告訴“Proxy”節點,讓他把部分原來轉發到S1節點的請求轉發到我這裡來。這樣子通過服務分流減少壓力的方法就可以解決原來S1節點性能不足的問題了。

nginx 反向代理_了解Nginx的反向代理與負載均衡

接着是第二個問題,單點伺服器挂掉了怎麼辦。還是考慮Server節點S1和S2,兩者所能夠提供的服務是一樣的,假設某一個時候S1挂掉了,這時如果有“Proxy”節點的存在,并且“Proxy”節點能夠察覺到S1挂掉了的話,那麼讓“Proxy”節點把原來要轉發給S1節點的請求轉發到S2進行處理就可以了,這樣子通過服務備援的方法就可以解決原來S1突然挂掉影響服務的問題。

nginx 反向代理_了解Nginx的反向代理與負載均衡

解決了這兩個問題,接下來我們再從這兩個問題裡面“Proxy”的角色來了解什麼叫做代理。

在第一個問題裡面,“Proxy”節點通過服務分流的方法來減少S1的壓力,對于原來應該被S1服務的,卻由于被“Proxy”節點轉發而被S2服務的Client而言,Client他并不知道實際上是由S1處理的還是S2處理的,Client拿到的是一個從“Proxy”節點傳回的結果,換言之,Client并不知道自己的請求實際上是被哪個處理的,他隻需要往“Proxy”節點發送請求就好了,剩下的工作就由“Proxy”節點去解決。

也就是,“Proxy”節點相當于一個中介,或者說是一個代理,代理Client去尋找實際的Server節點去完成服務。這樣子的模式在現實生活也非常常見,在買房子的時候,通常由房産中介幫助你完成和賣者之間的手續,而不需要你親自去處理這些事情,你隻需要協調好自己與中介之間的手續就好了,這裡的中介,就和我們的“Proxy”節點所做的工作非常類似。

同樣的,在第二個問題裡面,也是相似的了解方式,Client并不需要感覺S1是否還能正常工作,Client隻需要把請求發送給“Proxy”節點,由它去幫忙處理就可以了。

是以,這裡面的“Proxy”節點,也就是我們的代理節點。

正向代理與反向代理

了解了什麼是“代理”,離我們了解什麼是“反向代理”就隻差“反向”兩個字了,與“反向”相對的,就是“正向”,本質上來講,代理都是存在于Client和Server之間,但是由于性質不同,是以也分為這兩種。在這一個部分,我們将會學習,什麼是反向代理,什麼是正向代理。

直覺的以兩個例子去了解什麼是正向代理和反向代理。假設由A、B和C三人,他們之間存在借錢的關系。

對于正向代理,了解起來就是:

  1. A需要錢,A知道C由很多錢,想向C借錢
  2. 但是A和C有沖突,于是A想到通過B去借C借錢
  3. B向C借到錢了,C不知道是A的存在
  4. 這樣B就幫助A借到了Z的錢

    在這個過程,B就充當了代理借錢的角色,并且是代替A去借錢的,這樣就是正向代理。

nginx 反向代理_了解Nginx的反向代理與負載均衡

接着是反向代理:

  1. A需要錢,C有很多錢,A不知道C很多錢
  2. A找B借錢
  3. B知道C有很多錢
  4. B向C借錢,并把借到的錢給A,而沒有使用自己的錢借給A
  5. A拿到錢以後,以為錢是B的,A不知道C的存在

    在這個過程當中,B也充當了代理借錢的角色,不過這次不是代替A去借的,而是用C的錢借給A的,換言之即是代替C将錢借給了A,這就是反向代理。

    在例子裡面,把A換成Client,把C換成Server,就是計算機的例子了。

兩者差別
  1. 服務對象不同正向代理,代理的是用戶端,也就是例子中的A,服務端不知道實際發起請求的用戶端反向代理,代理的是服務端,也就是例子中的C,用戶端不知道實際提供服務的服務端

正向代理

nginx 反向代理_了解Nginx的反向代理與負載均衡

反向代理

nginx 反向代理_了解Nginx的反向代理與負載均衡
  1. 安全模型不同正向代理允許用戶端通過它通路任意網站并且隐藏用戶端自身,是以必須采取安全措施以確定僅為授權的用戶端提供服務反向代理都對外都是透明的,通路者并不知道自己通路的是代理,通路者不知道服務節點的存在,認為處理請求的就是代理節點

總而言之,正向代理是從用戶端的角度出發,服務于區域網路使用者,以通路非特定的服務,其中最典型的例子就是翻牆;反向代理正好與此相反,從服務端的角度出發,服務于所有使用者,隐藏實際的服務節點,服務節點的架構對使用者透明,以代理節點統一對外服務。

Nginx配置反向代理

(文末附完整nginx.conf配置)

為了示範Server節點, 我們使用Django快速啟動一個項目,可以快速驗證反向代理的配置是否ok。

django-admin startproject server1
           

接着我們啟動一個内網位址,端口為8080。

python manage.py runserver 127.0.0.1:8080
           

接着配置Nginx,在Nginx的配置裡面,主要是upstream塊,和server塊。

upstream httpserver{    server 127.0.0.1:8080;}
           

然後在server塊配置轉發到upstream。

location / {    proxy_pass http://httpserver;}
           

如此,便完成反向代理的配置,接着通過指令nginx -s reload重新加載配置檔案即可。若存在多個Server節點,在upstream域添加多個Server的位址即可。

我們另起一個django項目,服務啟動在8081端口。

接着更新upstream的配置。

upstream httpserver{    server 127.0.0.1:8080;    server 127.0.0.1:8081;}
           

就可以完成兩個節點的反向代理。

Nginx代理中的負載均衡

提到Nginx的反向代理,不得不提的就是Nginx的負載均衡,Nginx支援豐富的負載均衡算法,以提高使用Nginx部署的服務的綜合性能。

在介紹負載均衡之前,我們先來看為什麼需要負載均衡。

為什麼需要負載均衡

需要負載均衡的一個最簡單的訴求就是由Proxy代理的多個Server節點的性能并不完全相等的,也即是不同Server節點,他們處理請求的速度和容量都不相同,這就要求Proxy在轉發的時候,能夠因Server而異,給不同Server轉發适合其處理性能的請求量,以防Server節點低負載浪費資源,或者過高負載引起當機。

其次就是如果沒有負載均衡算法,我們就無法避免很多請求被排程到一個Server節點進而把這個Server節點壓垮的情況發生,因為我們沒有一種機制保證不同Server節點所處理的請求量數均勻的或者是合理的。

負載均衡的算法

對伺服器性能的考究有很多變量需要去關注:包括CPU的核數和頻率、記憶體的容量速度、網絡的品質、核心最大檔案描述符、伺服器的其他服務影響等等,是以在負載均衡算法上,也是非常豐富的,以下是幾種常見的負載均衡算法。

随機算法

随機,顧名思義,就是随機機率的排程,每一個請求通過随機算法排程到不同的伺服器,若調用量越大,不同伺服器處理的請求數就越平均。

這種算法看是公平的,但是沒有考慮到不同節點性能的差異,同時對随機算法也有一定的要求,要求随機算法在大量的随機事件後能夠得到一個均勻的随機結果。

輪詢算法

輪詢算法也非常容易了解,請求到來的時候,按順序把每個請求轉發到多個Server節點當中,保證每個服務節點所處理的請求量都是均勻的。

雖然這種算法很公平,但是沒有考慮到不同節點性能的差異。

最少連接配接算法

在多個伺服器當中,優先将請求排程到處理連接配接數少的伺服器上,即使每台伺服器的處理能力各不相同,也能夠在一定程度上降低伺服器的負載。

這種算法能夠考慮不同節點性能之間的差異,處理連接配接數在一定程度上能夠反映其性能的差異,不過并非絕對,在一些條件下,其他原因也可限制處理連接配接數,比如網絡性能、帶寬壓力等等。

權重輪詢算法

這種算法要求在轉發節點配置Server的時候,添加Server節點的權重資訊,以表示不同Server節點的處理性能,在轉發節點轉發請求的時候,将按照權重的大小來配置設定轉發的流量。

這種算法可以合理的轉發請求,開發人員可以按照Server節點的性能參數、部署的服務來修改Server節點的權重,使得每一個Server節點都能夠得到最合理的使用。

當然,除了開發人員手動配置權重以外,更為智能的一種方式是由代理的Server節點主動上報自己的能力,轉發節點在接收到相關資訊的時候再權衡不同Server節點的能力,按照權重進行轉發。這樣就不用人工介入,提高效率。不過這種方式對轉發節點和Server節點都有一定的要求,需要開發者去開發相關的邏輯。

使用Nginx配置負載均衡

了解不同的負載均衡算法以後,接下來就是對Nginx配置負載均衡了。Nginx支援普通輪詢算法和權重輪詢算法的負載均衡配置。

輪詢算法的負載均衡

其實基于普通輪詢算法的負載均衡,在前面我們已經實作了,隻不過當時重點不在負載均衡,是以沒有提及。

upstream httpserver{    server 127.0.0.1:8080;     server 127.0.0.1:8081;}
           

這就是輪詢算法的負載均衡的配置,在upstream配置塊的多個server節點預設都有權重weight=1,也即是每個服務節點權重一樣了。

權重輪詢算法的負載均衡

在普通輪詢算法的基礎上,我們可以進行權重輪詢算法的配置,配置如下:

upstream httpserver{    server 127.0.0.1:8080 weight=5;   # 權重為5    server 127.0.0.1:8081 weight=2;   # 權重為2    server 127.0.0.1:8082; # 預設權重為1}
           

如此添加weight關鍵字即可,接着你就可以在日志中看到,請求大緻會以5:2:1的比例落到三個server中,這就是權重輪詢算法的負載均衡。

總結

Nginx是一個高性能的部署服務端。支援HTTP部署、代理和反向代理、負載均衡、郵件服務等豐富的功能,是非常出色的一款軟體,本文介紹了反向代理和負載均衡的概念,并介紹了使用Nginx配置反向代理和負載均衡的過程,希望看完這篇文章,大家對Nginx和相關概念有進一步的了解。

最後打個小廣告,實戰課程《Django 2.0+微信小程式打造個人助手》,除了使用Django和微信小程式這兩款熱門技術去開發個人助手以外,針對Django的服務高可用部署等知識點也有詳細的介紹,感興趣的同學可以參加學習,我們一起來探讨哦。

附:最簡單Nginx的完整配置

user www-data;worker_processes auto;pid /run/nginx.pid;events {        worker_connections 768;}http {        ##        # Basic Settings        ##        sendfile on;        tcp_nopush on;        tcp_nodelay on;        keepalive_timeout 65;        types_hash_max_size 2048;        include /etc/nginx/mime.types;        default_type application/octet-stream;        ##        # SSL Settings        ##        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE        ssl_prefer_server_ciphers on;        ##        # Logging Settings        ##        access_log /var/log/nginx/access.log;        error_log /var/log/nginx/error.log;        ##        # Gzip Settings        ##        gzip on;        gzip_disable "msie6";        include /etc/nginx/conf.d/*.conf;        include /etc/nginx/sites-enabled/*;        upstream httpserver {                server 127.0.0.1:8080 weight=5;                server 127.0.0.1:8081 weight=2;        }        server {                listen 80;                server_name .dongcia.com;                charset utf-8;                location / {                       proxy_pass http://httpserver;                }        }}
           

作者:咚咚嗆

連結:http://www.imooc.com/article/284807

來源:慕課網

繼續閱讀