有机视频网zz视频国产,善良的妽妽8在线观看,无码不卡免费一级毛片视频,日本一区二区不卡

基于 Nginx 的軟件負載均衡實現(xiàn)解

2017-08-29 12:49

負載均衡在服務端開發(fā)中算是一個比較重要的特性。因為Nginx除了作為常規(guī)的Web服務器外,還會被大規(guī)模的用于反向代理前端,因為Nginx的異步框架可以處理很大的并發(fā)請求,把這些并發(fā)請求hold住之后就可以分發(fā)給后臺服務端(backend servers,也叫做服務池, 后面簡稱backend)來做復雜的計算、處理和響應,這種模式的好處是相當多的:隱藏業(yè)務主機更安全,節(jié)約了公網(wǎng)IP地址,并且在業(yè)務量增加的時候可以方便地擴容后臺服務器。

 

 

負載均衡可以分為硬件負載均衡和軟件負載均衡,前者一般是專用的軟件和硬件相結(jié)合的設(shè)備,設(shè)備商會提供完整成熟的解決方案,通常也會更加昂貴。軟件的復雜均衡以Nginx占據(jù)絕大多數(shù),本文也是基于其手冊做相應的學習研究的。

 

 

一、基本簡介

負載均衡涉及到以下的基礎(chǔ)知識。
  

(1) 負載均衡算法


  a. Round Robin: 對所有的backend輪訓發(fā)送請求,算是最簡單的方式了,也是默認的分配方式;


  b. Least Connections(least_conn): 跟蹤和backend當前的活躍連接數(shù)目,最少的連接數(shù)目說明這個backend負載最輕,將請求分配給他,這種方式會考慮到配置中給每個upstream分配的weight權(quán)重信息;


  c. Least Time(least_time): 請求會分配給響應最快和活躍連接數(shù)最少的backend;


  d. IP Hash(ip_hash): 對請求來源IP地址計算hash值,IPv4會考慮前3個octet,IPv6會考慮所有的地址位,然后根據(jù)得到的hash值通過某種映射分配到backend;


  e. Generic Hash(hash): 以用戶自定義資源(比如URL)的方式計算hash值完成分配,其可選consistent關(guān)鍵字支持一致性hash特性;

 


(2) 會話一致性
  

用戶(瀏覽器)在和服務端交互的時候,通常會在本地保存一些信息,而整個過程叫做一個會話(Session)并用唯一的Session ID進行標識。會話的概念不僅用于購物車這種常見情況,因為HTTP協(xié)議是無狀態(tài)的,所以任何需要邏輯上下文的情形都必須使用會話機制,此外HTTP客戶端也會額外緩存一些數(shù)據(jù)在本地,這樣就可以減少請求提高性能了。如果負載均衡可能將這個會話的請求分配到不同的后臺服務端上,這肯定是不合適的,必須通過多個backend共享這些數(shù)據(jù),效率肯定會很低下,最簡單的情況是保證會話一致性——相同的會話每次請求都會被分配到同一個backend上去。
  

 

(3) 后臺服務端的動態(tài)配置
  

出問題的backend要能被及時探測并剔除出分配群,而當業(yè)務增長的時候可以靈活的添加backend數(shù)目。此外當前風靡的Elastic Compute云計算服務,服務商也應當根據(jù)當前負載自動添加和減少backend主機。


  

(4) 基于DNS的負載均衡
  

通常現(xiàn)代的網(wǎng)絡服務者一個域名會關(guān)連到多個主機,在進行DNS查詢的時候,默認情況下DNS服務器會以round-robin形式以不同的順序返回IP地址列表,因此天然將客戶請求分配到不同的主機上去。不過這種方式含有固有的缺陷:DNS不會檢查主機和IP地址的可訪問性,所以分配給客戶端的IP不確保是可用的(Google 404);DNS的解析結(jié)果會在客戶端、多個中間DNS服務器不斷的緩存,所以backend的分配不會那么的理想。

 

 

二、Nginx中的負載均衡

  

Nginx中的負載均衡配置在手冊中描述的極為細致,此處就不流水帳了。對于常用的HTTP負載均衡,主要先定義一個upstream作為backend group,然后通過proxy_pass/fastcgi_pass等方式進行轉(zhuǎn)發(fā)操作,其中fastcgi_pass幾乎算是Nginx+PHP站點的標配了。

 

 

2.1 會話一致性

  

Nginx中的會話一致性是通過sticky開啟的,會話一致性和之前的負載均衡算法之間并不沖突,只是需要在第一次分配之后,該會話的所有請求都分配到那個相同的backend上面。目前支持三種模式的會話一致性:
  

(1). Cookie Insertion
  

在backend第一次response之后,會在其頭部添加一個session cookie,即由負載均衡器向客戶端植入 cookie,之后客戶端接下來的請求都會帶有這個cookie值,Nginx可以根據(jù)這個cookie判斷需要轉(zhuǎn)發(fā)給哪個backend了。

 

sticky cookie srv_id expires=1h domain=.example.com path=/;

  

上面的srv_id代表了cookie的名字,而后面的參數(shù)expires、domain、path都是可選的。
  

(2). Sticky Routes
  

也是在backend第一次response之后,會產(chǎn)生一個route信息,route信息通常會從cookie/URI信息中提取。

sticky route $route_cookie $route_uri;

  

這樣Nginx會按照順序搜索routecookie、route_uri參數(shù)并選擇第一個非空的參數(shù)用作route,而如果所有的參數(shù)都是空的,就使用上面默認的負載均衡算法決定請求分發(fā)給哪個backend。
  

(3). Learn
  

較為的復雜也較為的智能,Nginx會自動監(jiān)測request和response中的session信息,而且通常需要回話一致性的請求、應答中都會帶有session信息,這和第一種方式相比是不用增加cookie,而是動態(tài)學習已有的session。
  

這種方式需要使用到zone結(jié)構(gòu),在Nginx中zone都是共享內(nèi)存,可以在多個worker process中共享數(shù)據(jù)用的。(不過其他的會話一致性怎么沒用到共享內(nèi)存區(qū)域呢?)

 

sticky learn 

   create=$upstream_cookie_examplecookie

   lookup=$cookie_examplecookie

   zone=client_sessions:1m

   timeout=1h;

 

2.2 Session Draining

 

主要是有需要關(guān)閉某些backend以便維護或者升級,這些關(guān)鍵性的服務都講求gracefully處理的:就是新的請求不會發(fā)送到這個backend上面,而之前分配到這個backend的會話的后續(xù)請求還會繼續(xù)發(fā)送給他,直到這個會話最終完成。

  

讓某個backend進入draining的狀態(tài),既可以直接修改配置文件,然后按照之前的方式通過向master process發(fā)送信號重新加載配置,也可以采用Nginx的on-the-fly配置方式。

 

$ curl http://localhost/upstream_conf?upstream=backend

$ curl http://localhost/upstream_conf?upstream=backend\&id=1\&drain=1

 

通過上面的方式,先列出各個bacnkend的ID號,然后drain指定ID的backend。通過在線觀測backend的所有session都完成后,該backend就可以下線了。

 

2.3 backend健康監(jiān)測

 

backend出錯會涉及到兩個參數(shù),max_fails=1 fail_timeout=10s;意味著只要Nginx向backend發(fā)送一個請求失敗或者沒有收到一個響應,就認為該backend在接下來的10s是不可用的狀態(tài)。

  

通過周期性地向backend發(fā)送特殊的請求,并期盼收到特殊的響應,可以用以確認backend是健康可用的狀態(tài)。通過health_check可以做出這個配置。

 

match server_ok {

    status 200-399;

    header Content-Type = text/html;

    body !~ "maintenance mode";

}

server {

    location / {

        proxy_pass http://backend;

        health_check interval=10 fails=3 passes=2 match=server_ok;

    }

}

 

上面的health_check是必須的,后面的參數(shù)都是可選的。尤其是后面的match參數(shù),可以自定義服務器健康的條件,包括返回狀態(tài)碼、頭部信息、返回body等,這些條件是&&與關(guān)系。默認情況下Nginx會相隔interval的間隔向backend group發(fā)送一個”/“的請求,如果超時或者返回非2xx/3xx的響應碼,則認為對應的backend是unhealthy的,那么Nginx會停止向其發(fā)送request直到下次改backend再次通過檢查。

  

在使用了health_check功能的時候,一般都需要在backend group開辟一個zone,在共享backend group配置的同時,所有backend的狀態(tài)就可以在所有的worker process所共享了,否則每個worker process獨立保存自己的狀態(tài)檢查計數(shù)和結(jié)果,兩種情況會有很大的差異哦。

 

2.4 通過DNS設(shè)置HTTP負載均衡

 

Nginx的backend group中的主機可以配置成域名的形式,如果在域名的后面添加resolve參數(shù),那么Nginx會周期性的解析這個域名,當域名解析的結(jié)果發(fā)生變化的時候會自動生效而不用重啟。

 

http {

    resolver 10.0.0.1 valid=300s ipv6=off;

    resolver_timeout 10s;

    server {

        location / {

            proxy_pass http://backend;

        }

    }

   

    upstream backend {

        zone backend 32k;

        least_conn;

        ...

        server backend1.example.com resolve;

        server backend2.example.com resolve;

    }

}

 

如果域名解析的結(jié)果含有多個IP地址,這些IP地址都會保存到配置文件中去,并且這些IP都參與到自動負載均衡。

 

2.5 TCP/UDP流量的負載均衡

 

通常,HTTP和HTTPS的負載均衡叫做七層負載均衡,而TCP和UDP協(xié)議的負載均衡叫做四層負載均衡。因為七層負載均衡通常都是HTTP和HTTPS協(xié)議,所以這種負載均衡相當于是四層負載均衡的特例化,均衡器可以根據(jù)HTTP/HTTPS協(xié)議的頭部(User-Agent、Language等)、響應碼甚至是響應內(nèi)容做額外的規(guī)則,達到特定條件特定目的的backend轉(zhuǎn)發(fā)的需求。

 

除了Nginx所專長的HTTP負載均衡,Nginx還支持TCP和UDP流量的負載均衡,適用于LDAP/MySQL/RTMP和DNS/syslog/RADIUS各種應用場景。這類情況的負載均衡使用stream來配置,Nginx編譯的時候需要支持–with-stream選項。查看手冊,其配置原理和參數(shù)和HTTP負載均衡差不多。

  

因為TCP、UDP的負載均衡都是針對通用程序的,所以之前HTTP協(xié)議支持的match條件(status、header、body)是沒法使用的。TCP和UDP的程序可以根據(jù)特定的程序,采用send、expect的方式來進行動態(tài)健康檢測。

 

match http {

    send      "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n";

    expect ~* "200 OK";

}

 

2.6 其他特性

 

slow_start=30s:防止新添加/恢復的主機被突然增加的請求所壓垮,通過這個參數(shù)可以讓該主機的weight從0開始慢慢增加到設(shè)定值,讓其負載有一個緩慢增加的過程。

  

max_conns=30:可以設(shè)置backend的最大連接數(shù)目,當超過這個數(shù)目的時候會被放到queue隊列中,同時隊列的大小和超時參數(shù)也可以設(shè)置,當隊列中的請求數(shù)大于設(shè)定值,或者超過了timeout但是backend還不能處理請求,則客戶端將會收到一個錯誤返回。通常來說這還是一個比較重要的參數(shù),因為Nginx作為反向代理的時候,通常就是用于抗住并發(fā)量的,如果給backend過多的并發(fā)請求,很可能會占用后端過多的資源(比如線程、進程非事件驅(qū)動),最終反而會影響backend的處理能力。