天天看點

負載均衡叢集解決方案 (二)Nginx

 Nginx是一個免費的,開源的,高性能的伺服器和反向代理伺服器軟體,同時它也可以為IMAP和POP3伺服器代理,以其高性能,穩定性,豐富的功能,結構簡單,低資源消耗的特性換來廣大運維者所喜愛。

Nginx與傳統的伺服器不同,不依賴線程來處理請求。相反,它使用一個更可擴充事件驅動架構(異步)。這種結構資源消耗較小,但更重要的是,可以承受較大的請求負荷。即使你不希望處理成千上萬的請求,你仍然可以受益于Nginx的高性能和小的記憶體占用,以及其豐富的功能。

Nginx的反向代理:

反向代理指以代理伺服器來接受Internet上的連接配接請求,然後将請求轉發給内部網絡上的伺服器,并将從伺服器上得到的結果傳回給Internet上請求連接配接到用戶端,此時代理伺服器對外就表現為一個伺服器,而此種工作模式類似于LVS-NET模型。

反向代理也可以了解為web伺服器加速,它是一種通過在繁忙的web伺服器和外部網絡之間增加的 一個高速web緩沖伺服器,用來降低實際的web伺服器的負載的一種技術。反向代理是針對web伺服器提高加速功能,所有外部網絡要通路伺服器時的所有請求都要通過它,這樣反向代理伺服器負責接收用戶端的請求,然後到源伺服器上擷取内容,把内容傳回給使用者,并把内容儲存在本地,以便日後再收到同樣的資訊請求時,它會将本地緩存裡的内容直接發給使用者,已減少後端web伺服器的壓力,提高響應速度。是以Nginx還具有緩存功能。

反向代理的工作流程:

1)使用者通過域名發出通路請求,該域名被解析為反向代理伺服器的IP位址;

2)反向代理伺服器接收使用者的請求;

3)反向代理伺服器在本地緩存查找是否存在目前使用者所請求的内容,找到則直接把内容傳回給使用者;

4)如果本地沒有使用者請求的内容,反向代理伺服器會以自己的身份去後端伺服器請求同樣的資訊内容,并把資訊内容發給使用者,如果資訊内容是可以被緩存的,則會将該内容緩存在代理伺服器的本地緩存中。

反向代理的好處:

1)解決了網站伺服器對外可見的問題,提高了網站伺服器的安全性;

2)節約了有限的IP位址資源,後端伺服器均可使用私有IP位址與代理伺服器進行通信;

3)加速了網站的通路速度,減輕了真是web伺服器的負荷。

(一)、排程算法

Nginx的upstream指令用于指定proxy_pass和fastcgi_pass所使用的後端伺服器,即nginx的反向代理功能,是以可以将兩者結合起來使用以達到負載均衡的目的,而Nginx也支援多種排程算法:

1、輪詢(預設)

每個請求按時間順序逐一配置設定到不同的後端伺服器,如果後端伺服器down掉,則會跳過該伺服器配置設定至下一個監控的伺服器。并且它無需記錄目前所有連接配接的狀态,是以它是一種無狀态排程。

2、weight

指定在輪詢的基礎上加上權重,weight和通路比率成正比,即用于表明後端伺服器的性能好壞,若後端伺服器性能較好則可将大部分請求配置設定給它,已實作其力所能及。

例如:

我後端伺服器172.23.136.148配置:E5520*2 CPU,8G記憶體

後端伺服器172.23.136.148配置:Xeon(TM)2.80GHz * 2,4G記憶體

我希望在有30個請求到達前端時,其中20個請求交給172.23.136.148處理,剩餘10個請求交給172.23.136.149處理,就可做如下配置

upstream web_poll {

server 172.23.136.148 weight=10;

server 172.23.136.149 weight=5;

}

3、ip_hash 

每個請求按通路ip的hash結果配置設定,當新的請求到達時,先将其用戶端IP通過雜湊演算法進行哈希出一個值,在随後的請求用戶端IP的哈希值隻要相同,就會被配置設定至同一個後端伺服器,該排程算法可以解決session的問題,但有時會導緻配置設定不均即無法保證負載均衡。

upstream web_pool {

ip_hash;

server 172.23.136.148:80;

server 172.23.136.149:80;

4、fair(第三方)

按後端伺服器的響應時間來配置設定請求,響應時間短的優先配置設定。

server 172.23.136.148;

server 172.23.136.149;

fair;

5、url_hash(第三方)

按通路url的hash結果來配置設定請求,使每個url定向到同一個後端伺服器,後端伺服器為緩存時比較有效。

例:在upstream中加入hash語句,server語句中不能寫入weight等其他的參數,hash_method是使用的hash算法

server squid1:3128;

server squid2:3128;

hash $request_uri;

hash_method crc32;

每個裝置的狀态設定為:

1.down 表示目前的server不參與負載,用于ip_hash中

2.weight 預設為1.weight越大,負載的權重就越大。

3.max_fails 允許請求失敗的次數預設為1.設為0則表示關閉該項功能,當超過最大次數時,傳回proxy_next_upstream 子產品定義的錯誤

4.fail_timeout 在max_fails定義的失敗次數後,暫停的時間。

5.backup 可以将其了解為備機,其它所有的非backup機器down或者忙的時候,才會将請求配置設定給backup機器。是以這台機器壓力會最輕。

nginx支援同時設定多組的負載均衡,用來給不用的server來使用。

(二)、指令的使用

1、upstream

聲明一組可以被proxy_pass和fastcgi_pass引用的伺服器;這些伺服器可以使用不同的端口,并且也可以使用Unix Socket;也可以為伺服器指定不同的權重。如:

    server coolinuz.9966.org weight=5;

    server 172.23.136.148:8080 max_fails=3  fail_timeout=30s;

    server unix:/tmp/backend3;

2、server

文法:server name [parameters]

其中的name可以是FQDN,主機位址,端口或unix套接字;如果FQDN解析的結果為多個位址,則每個位址都會被用到。

3、proxy_pass

文法:proxy_pass URL;

該指令用于指定代理伺服器的位址和URL将被映射為的URL或位址和端口。即用來指定後端伺服器的位址或URL[端口]。

4、proxy_set_header

文法:proxy_set_header header value;

該指令允許重新定義和添加一些将被轉移到被代理伺服器的請求頭部資訊。

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

注意:$proxy_add_x_forwarded_for包含用戶端請求頭中的"X-Forwarded-For",與$remote_addr用逗号分開,如果沒有"X-Forwarded-For" 請求頭,則$proxy_add_x_forwarded_for等于$remote_addr

順便補上Nginx的内置變量:

$args, 請求中的參數;

$is_args, 如果已經設定$args,則該變量的值為“?”,否則為“”。

$content_length, HTTP請求資訊頭裡的"Content-Length";

$content_type, 請求資訊頭裡的"Content-Type";

$document_root, 針對目前請求所屬的root指令設定的根目錄路徑;

$document_uri, 與$uri相同;

$host, 請求資訊中的"Host",如果請求中沒有Host行,則等于設定的伺服器名;

$limit_rate, 對連接配接速率的限制;

$request_method, 請求的方法,比如"GET"、"POST"等;

$remote_addr, 用戶端位址;

$remote_port, 用戶端端口号;

$remote_user, 用戶端使用者名,認證用;

$request_filename, 目前請求的檔案路徑名

$request_body_file, 用戶端請求主體的臨時檔案名。

$request_uri, 請求的URI,帶參數;

$query_string, 與$args相同;

$scheme, 所用的協定,比如http或者是https,比如rewrite  ^(.+)$ $scheme://example.com$1  redirect;

$server_protocol, 請求的協定版本,"HTTP/1.0"或"HTTP/1.1";

$server_addr, 伺服器位址,如果沒有用listen指明伺服器位址,使用這個變量将發起一次系統調用以取得位址(造成資源浪費);

$server_name, 請求到達的伺服器名;

$server_port, 請求到達的伺服器端口号;

$uri, 請求的URI,可能和最初的值有不同,比如經過重定向之類的。

5、proxy_read_timeout

文法:proxy_read_timeout time;

這個指令設定Nginx與後端伺服器建立連接配接後。等待後端伺服器的響應時間

6、proxy_send_timeout

文法:roxy_send_timeout time;

該指令指定請求轉移到後端伺服器的逾時時間。整個傳輸的要求時間不超過逾時時間,但隻有兩次寫操作之間。如果在此時間之後的後端伺服器将不采取新的資料,然後nginx将關閉連接配接。

7、proxy_connect_timeout

文法:proxy_connect_timeout time;

該指令用來設定配置設定到後端伺服器的連接配接逾時時間。

8、proxy_buffers

文法: proxy_buffers the_number is_size;

該指令設定緩沖區的數目和大小,預設情況下,一個緩沖區的大小和頁面大小相同。

9、proxy_buffer_size

文法:proxy_buffer_size buffer_size;

代理緩沖區,該指令用于儲存用使用者的頭部資訊。

10、proxy_busy_buffers_size

文法:proxy_busy_buffers_size size;

用于當系統負載較大,緩沖區不夠用時,可以申請更大的proxy_buffers

11、proxy_temp_file_write_size

文法:proxy_temp_file_write_size size;

用于指定緩存臨時檔案的大小

(三)、功能完善

安裝配置第三方子產品,實作upstream中對後端web server的健康狀态檢測:

安裝配置方法:

1、首先解壓healcheck子產品到某路徑下,這裡假設為/tmp/healthcheck_nginx_upstreams

#tar -xvf cep21-healthcheck_nginx_upstreams-16d6ae7.tar.gz -C /tmp/healthcheck_nginx_upstreams

2、對nginx打更新檔

首先解壓nginx,并進入nginx源碼目錄:

# tar xf nginx-1.3.4.tar.gz

# cd nginx-1.0.11

# patch -p1 < /tmp/healthcheck_nginx_upstreams/nginx.patch

而後編譯nginx,在執行configure時添加類似下面的選項:

--add-module=/tmp/healthcheck_nginx_upstreams

是以,這裡就使用如下指令:

# ./configure \

--prefix=/usr/local/nginx \

--sbin-path=/usr/sbin/nginx \

--conf-path=/etc/nginx/nginx.conf \

--lock-path=/var/lock/nginx.lock \

--user=nginx \

--group=nginx \

--with-http_ssl_module \

--with-http_flv_module \

--with-http_stub_status_module \

--with-http_gzip_static_module \

--http-proxy-temp-path=/var/tmp/nginx/proxy/ \

--http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \

--with-pcre \

# make && make install

ngx_http_healthcheck_module子產品的使用方法:

1、此子產品支援的指令有:

healthcheck_enabled ##啟用此子產品

healthcheck_delay ##對同一台後端伺服器兩次檢測之間的時間間隔,機關毫秒,預設為1000;

healthcheck_timeout ##進行一次健康檢測的逾時時間,機關為毫秒,預設值2000;

healthcheck_failcount ##對一台後端伺服器檢測成功或失敗多少次之後方才确定其為成功或失敗,并實作啟用或禁用此伺服器;

healthcheck_send ##為了檢測後端伺服器的健康狀态所發送的檢測請求;如:healthcheck_send "GET /health HTTP/1.0" 'Host: coolinuz.9966.org';

healthcheck_expected ##期望從後端伺服器收到的響應内容;如果未設定,則表示從後端伺服器收到200狀态碼即為正确;

healthcheck_buffer ##健康狀态檢查所使用的buffer空間大小;

healthcheck_status

通過類似stub_status的方式輸出檢測資訊,使用方法如下:

location /stat {

  healthcheck_status;

(四)、配置與實作

配置代碼如下:

http {

  upstream web_pool {

    server 172.23.136.148:80 weight=10;

    server 172.23.136.149:80 weight=5;

    healthcheck_enabled;

    healthcheck_delay 1000;

    healthcheck_timeout 1000;

    healthcheck_failcount 2;

    healthcheck_send "GET /.health HTTP/1.0";

  }

  server {

    listen 80;

    location / {

      proxy_set_header Host $http_host;

      proxy_set_header X-Real-IP $remote_addr;

      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

      proxy_pass http://web_pool;

      proxy_connect_timeout 3;

    }

    location /stat {

      healthcheck_status;

  }

在這裡設定“proxy_set_header”參數,是因為Nginx在做反向代理的時候,要代替用戶端去通路伺服器,是以,當請求包經過反向代理後,在代理伺服器這裡這個IP資料包的IP標頭做了修改,最終後端web伺服器得到的資料包的頭部的源IP位址是代理伺服器的IP位址,這樣一來,後端伺服器的程式給予IP的統計功能就沒有任何意義,或者後端web伺服器上有多個基于域名的虛拟主機時,就要通過添加Header頭資訊Host,用于指定請求的域名,這樣後端web伺服器才能識别該反向代理通路請求由哪個虛拟主機來處理。

(五)、小結

通過以上我們可以看出Nginx的配置其實是比較其他的web伺服器軟體是比較簡單的,但是其實作的功能确實相當強大豐富的。通過Nginx的反向代理已經支援靈活的正規表達式比對,可以實作網站的動、靜分離,讓動态的php等程式網頁去通路php web伺服器,讓緩存頁、圖檔、javascript、css、flash去通路Squid等緩存伺服器或檔案伺服器。加之Nginx對靜态内容的高性能,高并發量,Nginx作為前端代理負載均衡成為越來越多架構師的首先方案。

本文轉自 向陽草米奇 51CTO部落格,原文連結:http://blog.51cto.com/grass51/985416,如需轉載請自行聯系原作者

繼續閱讀