1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        從 Nginx 看負(fù)載均衡

        共 7842字,需瀏覽 16分鐘

         ·

        2020-09-24 02:42

        閱讀本文大概需要 3 分鐘。


        眾所周知,Nginx ?是一個輕量級、高性能的 Web ?服務(wù)器,它的用途廣泛,上可作為各種服務(wù)的網(wǎng)關(guān),下可直接作為靜態(tài)網(wǎng)站的服務(wù)器,甚至還能被用來做代理服務(wù)器、負(fù)載均衡器、緩存服務(wù)器等。

        在目前流行的云服務(wù)架構(gòu)體系中,Nginx 經(jīng)常會被用于作為網(wǎng)關(guān)、負(fù)載均衡器之類的用途。在這其中,負(fù)載均衡器這個用途可以說是最為廣泛的了,畢竟但凡是個需要橫向擴(kuò)展的后端服務(wù),就都需要有個負(fù)載均衡器來頂在前面分發(fā)請求,而 Nginx 作為一個輕量又高性能的工具,自然是最合適的選擇之一。

        負(fù)載均衡概念

        負(fù)載均衡是一個基礎(chǔ)服務(wù),主要被用來在多個節(jié)點(diǎn)間分配負(fù)載,以做到最大化資源利用率和吞吐量、最小化響應(yīng)時(shí)間的效果,可以使服務(wù)盡可能地做到高并發(fā);同時(shí),負(fù)載均衡還能通過提供冗余節(jié)點(diǎn)、自動切換的方式提高可靠性,使得服務(wù)能盡可能地做到高可用。

        注意是從下往上數(shù)

        負(fù)載均衡主要分為兩種,一種是基于四層的、一種是基于七層的,這里的“層”指的是 OSI ?模型中的“層”的概念。四層指的是 TCP/UDP 這些最原始的協(xié)議所在的傳輸層,而七層指的是 HTTP、SSH 之類的這些上層協(xié)議所在的應(yīng)用層。

        兩者的主要區(qū)別在于:

        四層負(fù)載均衡

        因?yàn)橥ǔV恍枰鶕?jù)包的報(bào)文頭中的信息直接分配(轉(zhuǎn)發(fā))負(fù)載給節(jié)點(diǎn)就行,所以性能會更高、資源占用更低。但由于無法對上層協(xié)議的內(nèi)容進(jìn)行具體的解析(或者說做了解析就不再是四層了),所以可控性相比于七層的負(fù)載均衡而言會低很多。

        比如上面這張圖是一個 HTTP 請求包的第四層(及以下)的部分,可以得到的信息有來源 IP ?和端口、目標(biāo) IP 和端口等,而玩過 TCP 通信的朋友應(yīng)該知道,這些信息都是建立連接后就能得到的。而在做四層負(fù)載均衡的時(shí)候,我們并不需要理會具體傳輸?shù)膬?nèi)容就可以直接進(jìn)行轉(zhuǎn)發(fā),所以也就少了讀取具體內(nèi)容這個從內(nèi)核態(tài)轉(zhuǎn)到用戶態(tài)的步驟,性能自然也就會更高一些了。

        七層負(fù)載均衡

        可以做到根據(jù)客戶端信息、目錄結(jié)構(gòu)等來分配負(fù)載的效果,配置起來也更貼近于應(yīng)用。但由于需要處理具體的流量,所以七層負(fù)載均衡的性能相對低一些,并且由于需要對上層協(xié)議的內(nèi)容進(jìn)行解析,所以資源占用也相對會高一些。

        比如上面這張圖是一個 HTTP 請求包的第七層(及以下)的部分,我們可以直接看到它的 Method 是 GET、請求的路徑是?/speedtest.js、User-Agent 是 Mac 下的 Chrome的、Cookie 是 balabala 等。


        除了四層和七層的區(qū)別外,負(fù)載均衡還有硬件負(fù)載均衡和軟件負(fù)載均衡兩種做法:

        硬件負(fù)載均衡

        硬件負(fù)載均衡通常是在交換機(jī)上直接進(jìn)行操作,而這些設(shè)備通常還會有著專用的加速芯片,可以使得包的分發(fā)效率變得極高,所以性能上相比于軟件負(fù)載均衡而言,會要高很多。比如可以輕松地帶起上萬量級的節(jié)點(diǎn),并且還能承受住每秒幾百萬的負(fù)載。(順帶一提,軟路由和硬路由有時(shí)候性能差距極大也是因?yàn)檫@個原因)

        但硬件負(fù)載均衡的缺點(diǎn)很明顯:由于需要專用設(shè)備,所以成本也會高很多,一般根據(jù)功能和性能的不同,一個就得要十幾萬到上百萬,相當(dāng)昂貴。并且還會有部分硬件負(fù)載均衡器的配置項(xiàng)過于底層、只支持四層負(fù)載均衡,所以會有無法根據(jù)節(jié)點(diǎn)和應(yīng)用的實(shí)際狀況來分配負(fù)載的問題。

        所以,硬件負(fù)載均衡更適合于有海量負(fù)載、海量節(jié)點(diǎn)需要管理的場景,依靠著專用的加速芯片可以輕松處理在這種場景下的負(fù)載均衡問題。

        軟件負(fù)載均衡

        軟件負(fù)載均衡是基于系統(tǒng)和應(yīng)用的負(fù)載均衡,相比于硬件負(fù)載均衡而言,能夠更好地根據(jù)系統(tǒng)和應(yīng)用的情況來分配負(fù)載;同時(shí),由于不需要購買專用設(shè)備,隨便一個服務(wù)器就行,成本會低很多。

        軟件負(fù)載均衡的缺點(diǎn)也很明顯:雖然方便,但會受限于服務(wù)器的性能。如果服務(wù)器性能低下,那自然難以承受更多的負(fù)載,也就無法有效地將負(fù)載分配給各個節(jié)點(diǎn)。

        所以,軟件負(fù)載均衡更適合于負(fù)載量還達(dá)不到海量級,并且也沒有那么多的節(jié)點(diǎn)需要管理的場景;或是一些即使舍棄掉部分性能也必須要保證可控性、擴(kuò)展性的場景(比如加入了反爬蟲功能的網(wǎng)關(guān))。

        Nginx 負(fù)載均衡簡介

        那么 Nginx 的負(fù)載均衡,是什么樣的呢?

        Nginx 現(xiàn)在的負(fù)載均衡既支持四層(ngx_stream_core_module模塊)、又支持七層(ngx_http_upstream_module模塊),但由于 LVS 在四層負(fù)載均衡方面做得知名度實(shí)在是太高了,所以 Nginx 的四層負(fù)載均衡用的人不怎么多,網(wǎng)上也很少會有說用? Nginx 來做四層負(fù)載均衡的。

        Nginx 負(fù)載均衡方面的代碼設(shè)計(jì)非常模塊化,這方面在配置文件上也有所體現(xiàn)。不管是四層還是七層,都是用的同一套 upstream 配置,只是使用這個 upstream 的地方會有差別而已,所以四層和七層的差別其實(shí)對于我們的配置來說沒有影響,反正寫起來基本都是通用的。下面將以七層負(fù)載均衡為例講解。

        不過有一個點(diǎn)需要注意,在使用 Nginx 作為七層負(fù)載均衡器時(shí),如果 Nginx 上有設(shè)置?proxy_cache,那么如果被訪問的資源已經(jīng)被緩存過,Nginx 就不會再將請求轉(zhuǎn)發(fā)給節(jié)點(diǎn),而是直接返回緩存資源。也就是說在 Nginx 有配置緩存的情況下是有可能不會觸發(fā)調(diào)度的。

        Nginx 負(fù)載均衡常見的調(diào)度算法

        輪詢(默認(rèn)的模式)

        輪詢算法在被用于服務(wù)器的負(fù)載均衡時(shí)的表現(xiàn)為:按照客戶端的請求順序,逐一將請求分配到不同的后端節(jié)點(diǎn)服務(wù)器上。

        配置時(shí)只需要在 upstream 配置中添加 server 即可,在沒有指定 weight和其他調(diào)度算法的情況下,就是普通的輪詢。

        upstream balabala {    server 192.168.31.33;    server 192.168.31.237;}...location / {    proxy_pass http://balabala;}

        在碰到后端服務(wù)器無響應(yīng)的情況時(shí),Nginx會自動剔除這臺服務(wù)器,換到其他服務(wù)器上。

        加權(quán)輪詢

        加權(quán)輪詢算法在被用于服務(wù)器的負(fù)載均衡時(shí)的表現(xiàn)為:按照權(quán)重的大小來進(jìn)行分配,權(quán)重值越大的節(jié)點(diǎn),被分配到的請求就越多。例如現(xiàn)在有兩臺服務(wù)器,一臺的權(quán)重是5、另一臺的權(quán)重是1,那么權(quán)重為5的服務(wù)器被分配到的概率就會更高,被分配到的請求也就越多。

        加權(quán)輪詢通常被用于節(jié)點(diǎn)服務(wù)器性能不均勻的情況。比如可以給性能高的服務(wù)器設(shè)置高權(quán)重,使其負(fù)載更多請求,從而避免性能低的服務(wù)器被大量的請求壓垮。

        配置時(shí)只需要在輪詢配置的基礎(chǔ)上添加weight參數(shù)即可。

        upstream balabala {    server 192.168.31.33 weight=1;    server 192.168.31.237 weight=1;}...location / {    proxy_pass http://balabala;}

        ip_hash

        ip_hash是一個靜態(tài)調(diào)度算法,也是一種非一致性Hash算法。它會把每個請求按照客戶端IP的Hash結(jié)果來分配給節(jié)點(diǎn),使得同一個客戶端IP的請求能夠始終分配到同一個節(jié)點(diǎn)上(無論請求的是哪個URL)。然而由于是非一致性Hash算法,所以一旦節(jié)點(diǎn)數(shù)量發(fā)生變化,所有的分配映射關(guān)系就都會發(fā)生改變,在節(jié)點(diǎn)配置不穩(wěn)定的情況下會無法達(dá)到預(yù)期的效果。

        由于ip_hash算法可以使同一個客戶端IP的請求始終被分配到同一個節(jié)點(diǎn)上,所以它可以有效地解決動態(tài)頁面的session共享問題,也就是做到保持會話的效果。但是它有時(shí)也會導(dǎo)致請求分配不均,無法保證所有節(jié)點(diǎn)都能分配到一樣的請求量。

        由于IPV4資源緊缺,目前國內(nèi)IPV4的IP通常都是會經(jīng)過NAT的,所以很容易出現(xiàn)多個客戶端同時(shí)使用同一個IP的情況。而在使用ip_hash的時(shí)候,這些使用著同一個IP的客戶端就都會被分配到同一個節(jié)點(diǎn)上,從而導(dǎo)致出現(xiàn)請求分配不均的情況。

        注:LVS中的-p參數(shù)、Keepalived 配置里的per-sistence_timeout 50參數(shù),以及 Nginx 中的?ip_hash參數(shù),其功能都可以用來解決動態(tài)頁面的session共享問題。

        配置時(shí)只需要在 upstream 配置中加一行?ip_hash;即可。注意不能與 backup 配置共同使用,因?yàn)?ip_hash 只能訪問同一臺服務(wù)器,而 backup 只有在所有參與負(fù)載均衡的服務(wù)器出現(xiàn)故障時(shí),才會被訪問。而如果所有參與負(fù)載均衡的服務(wù)器出現(xiàn)故障了的時(shí)候,ip_hash 就不能用了。

        upstream balabala {        ip_hash;        server 192.168.31.33 weight=1;        server 192.168.31.237 weight=1;}...location / {        proxy_pass http://balabala;}

        hash(一般是稱之為 uri_hash)

        hash 是一個靜態(tài)調(diào)度算法,也是一種非一致性Hash算法。它會把每個請求按照客戶端的IP、請求的URI的Hash結(jié)果(參數(shù)可選,主流使用URI)來分配給節(jié)點(diǎn),使得同一個URI的請求能夠始終分配到同一個節(jié)點(diǎn)上(無論來自于哪個客戶端)。然而由于是非一致性Hash算法,所以一旦節(jié)點(diǎn)數(shù)量發(fā)生變化,所有的分配映射關(guān)系就都會發(fā)生改變,在節(jié)點(diǎn)配置不穩(wěn)定的情況下會無法達(dá)到預(yù)期的效果。

        由于hash算法可以使同一個URI的請求始終被分配到同一個節(jié)點(diǎn)上,所以它非常適合在節(jié)點(diǎn)服務(wù)器為緩存服務(wù)器的情況下使用,能夠大大地提高緩存命中率。

        Nginx在1.7.2版本之前并不支持hash算法,如果需要在舊版本中使用這種算法,就需要安裝第三方的hash模塊。

        配置時(shí)只需要在upstream配置中加一行hash $request_uri;和一行hash_method crc32;即可,兩個的參數(shù)均可被替換為其他內(nèi)容,如有需要請參閱Nginx官方文檔。

        upstream balabala {        hash $request_uri;        hash_method crc32;        server 192.168.31.33;        server 192.168.31.237;}...location / {        proxy_pass http://balabala;}

        fair

        fair 是一個動態(tài)調(diào)度算法,它會根據(jù)節(jié)點(diǎn)服務(wù)器的響應(yīng)時(shí)間來分配請求,響應(yīng)時(shí)間短的會被優(yōu)先分配。

        Nginx 本身并不支持 fair 算法,如果需要使用這種算法,就需要安裝第三方的?upstream_fair模塊。

        配置時(shí)只需要在 upstream 配置中加一行?fair;即可。

        upstream balabala {        fair;        server 192.168.31.33;        server 192.168.31.237;}...location / {        proxy_pass http://balabala;}

        least_conn

        least_conn 是一個動態(tài)調(diào)度算法,它會根據(jù)節(jié)點(diǎn)服務(wù)器的連接數(shù)情況來分配請求,連接數(shù)少的會被優(yōu)先分配。

        least_conn 可以被用于有大量長連接的場景(比如游戲服務(wù)器),它可以幫助節(jié)點(diǎn)服務(wù)器均分連接,使負(fù)載盡可能地保持相同。

        least_conn? 算法很簡單,它會先遍歷一遍所有的節(jié)點(diǎn),比較它們的連接數(shù),然后選取值最小的那一個節(jié)點(diǎn)。如果有多個節(jié)點(diǎn)的連接數(shù)值都是最小的,那么就對它們采用加權(quán)輪詢算法。

        配置時(shí)只需要在 upstream 配置中加一行?least_conn;即可,可以結(jié)合?weight權(quán)重值使用。

        upstream balabala {        least_conn;        server 192.168.31.33;        server 192.168.31.237;}...location / {        proxy_pass http://balabala;}

        consistent_hash

        consistent_hash 是一個基于一致性 Hash 算法產(chǎn)生的靜態(tài)調(diào)度算法,它是 ip_hash 和 hash 的升級版。

        consistent_hash 同樣會把每個請求按照客戶端的 IP、請求的 URI 的 Hash 結(jié)果(參數(shù)可選)來分配給節(jié)點(diǎn),使得同一個 Hash 值的請求能夠始終分配到同一個節(jié)點(diǎn)上。它的獨(dú)特之處在于,一致性 Hash 算法為它提供了故障遷移和一致性保持的效果。也就是說,即使在使用過程中某一個節(jié)點(diǎn)宕機(jī)了,其他 Hash 值和對應(yīng)的節(jié)點(diǎn)也還是不會受影響,仍然可以保持原來的映射關(guān)系;而這一個宕機(jī)的節(jié)點(diǎn)所對應(yīng)的那些 Hash 值,會被映射到環(huán)上的下一個節(jié)點(diǎn)上,達(dá)到故障遷移的效果。

        配置時(shí)和hash類似,只需要在 upstream 配置中加一行consistent_hash $request_uri;即可。同樣,這個參數(shù)也是可以替換為其他內(nèi)容的。

        upstream balabala {        consistent_hash $request_uri;        server 192.168.31.33;        server 192.168.31.237;}...location / {        proxy_pass http://balabala;}

        常用的相關(guān)參數(shù)/配置項(xiàng)說明

        keepalive

        為每個 worker 進(jìn)程保留的長連接數(shù)量,可以節(jié)約端口開銷,并減少連接管理的資源消耗。

        配置時(shí)只需要在 upstream 配置中加一行keepalive 連接數(shù);即可。

        upstream balabala {        fair;        keepalive 123;        server 192.168.31.33;        server 192.168.31.237;}...location / {        proxy_pass http://balabala;}

        proxy_next_upstream

        proxy_next_upstream 被用于定義故障轉(zhuǎn)移策略,當(dāng) server 返回指定的http status code、請求超時(shí)等錯誤時(shí),就會自動將請求轉(zhuǎn)發(fā)到 upstream 中的另一臺服務(wù)器,實(shí)現(xiàn)故障轉(zhuǎn)移。

        配置時(shí)只需要在 location 配置中添加一行proxy_next_upstream 具體的http status code或錯誤類型;即可。可以指定多個需要轉(zhuǎn)移的選項(xiàng),只需要用空格分隔開就行。

        可用的配置項(xiàng)例如(更多配置項(xiàng)請參閱Nginx官方文檔):

        ?http_500?http_502?error?timeout?invalid_header

        upstream balabala {        fair;        keepalive 123;        server 192.168.31.33 max_fails=3 fail_timeout=10s;        server 192.168.31.237 max_fails=3 fail_timeout=10s;}...location / {        proxy_pass http://balabala;        proxy_next_upstream http_500 http_502 error timeout invalid_header;}

        server

        server參數(shù)后面跟著的地址可為多種不同格式,如:

        ?unix:/PATH/TO/SOME_SOCK_FILE?IP[:PORT]?HOSTNAME[:PORT]

        server配置項(xiàng)

        down

        down表示當(dāng)前server暫時(shí)不參與負(fù)載均衡,也就是將server標(biāo)記為不可用狀態(tài)。

        down可以配合ip_hash來使用,實(shí)現(xiàn)灰度發(fā)布的效果。

        配置時(shí)只需要在server后面指定down參數(shù)即可。

        backup

        backup表示當(dāng)前server是預(yù)留的備份機(jī)器

        只有其他所有的非backup機(jī)器出現(xiàn)故障或者忙的時(shí)候,才會請求backup機(jī)器

        backup可以被用來做到sorry server的效果,也就是在后端服務(wù)器掛了的時(shí)候給個“對不起,網(wǎng)站暫時(shí)無法訪問”之類的頁面,用來提示用戶。相比于將特定http status code的頁面配置為類似效果的做法,這種做法的優(yōu)勢在于不會出現(xiàn)很長時(shí)間的超時(shí)等待,而是立馬返回錯誤提示,用戶體驗(yàn)會更好一些。

        配置時(shí)只需要在server后面指定backup參數(shù)即可。

        max_conns

        Nginx在1.11.5版本后新增的參數(shù),指連接某后端服務(wù)器時(shí)的最大并發(fā)活動連接數(shù)。

        配置時(shí)只需要在server后面指定max_conns 連接數(shù);即可。

        max_fails

        允許請求失敗的次數(shù),默認(rèn)為1。當(dāng)超出最大次數(shù)時(shí),該server會被標(biāo)記為不可用。

        fail_timeout

        在經(jīng)歷了max_fails次失敗后,暫停服務(wù)的時(shí)間,默認(rèn)為10s。某個server連接失敗次數(shù)超過max_fails次后,nginx就會在接下來的fail_timeout的時(shí)間內(nèi)不再分發(fā)請求給這個server。

        配置時(shí)只需要在server后面指定max_fails參數(shù)即可。值為數(shù)值+單位,如10s等同于10秒。fail_timeout一般會結(jié)合max_fails使用。

        upstream balabala {        server 192.168.31.33 max_fails=3 fail_timeout=10s;        server 192.168.31.237 max_fails=3 fail_timeout=10s;}

        總結(jié)

        負(fù)載均衡在提升性能、負(fù)載量、可用率等情況下都會有用到,且對于后端整個大方向(包括爬蟲在內(nèi))的各種場景均有著用武之地。在使用負(fù)載均衡時(shí),需要根據(jù)實(shí)際的業(yè)務(wù)情況來選擇對應(yīng)的調(diào)度方式和調(diào)度算法,以達(dá)到最大化收益的效果。

        另外,像寫爬蟲的時(shí)候,有些場景我們也可以使用到負(fù)載均衡,但我們并不一定是要用Nginx來做,而是自己在代碼中去實(shí)現(xiàn),所以了解一下基本的思路和原理還是很有必要的。

        文檔鏈接、配置樣例等資源

        由于存在更新的可能性,所以我決定將這些東西放到自動回復(fù)中,你可以發(fā)送消息【Nginx負(fù)載均衡】到公眾號【NightTeam】獲取。


        推薦閱讀

        1

        我這幾年踩過的十個坑,每一條都是血淚教訓(xùn)

        2

        Alfred 有多強(qiáng)悍,我寫了個一鍵上傳圖片的 workflow 來告訴你

        3

        手把手教學(xué),如何解決 Git 沖突?

        4??

        中國最懶城市,這里的人不想賺錢,只想躺平




        崔慶才

        靜覓博客博主,《Python3網(wǎng)絡(luò)爬蟲開發(fā)實(shí)戰(zhàn)》作者

        隱形字

        個人公眾號:進(jìn)擊的Coder

        長按識別二維碼關(guān)注





        好文和朋友一起看~
        瀏覽 68
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美成人精品网站 | 啊灬啊灬啊灬快灬高潮了女视频 | 国产午夜在线 | 北条麻妃被操 | 老熟女亂伦一区二区三区在线视频 | 中文字幕日韩精品人妻 | 在线免费亚洲视频 | ZZjiZZji亚洲日本少妇 | 成人美女黄网站色大免费的 | 黄色美女网 |