負載均衡集羣解決方案-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(第三方)
按後端服務器的響應時間來分配請求,響應時間短的優先分配。
upstream web_pool {
server 172.23.136.148;
server 172.23.136.149;
fair;
}
5、url_hash(第三方)
按訪問url的hash結果來分配請求,使每個url定向到同一個後端服務器,後端服務器爲緩存時比較有效。
例:在upstream中加入hash語句,server語句中不能寫入weight等其他的參數,hash_method是使用的hash算法
upstream web_pool {
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;也可以爲服務器指定不同的權重。如:
upstream web_pool {
    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的健康狀態檢測:
模塊下載地址:https://github.com/cep21/healthcheck_nginx_upstreams;模塊名稱:ngx_http_healthcheck_module
安裝配置方法:
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 \
--add-module=/tmp/healthcheck_nginx_upstreams
# 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作爲前端代理負載均衡成爲越來越多架構師的首先方案。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章