1. 程式人生 > >負載均衡叢集解決方案 Nginx

負載均衡叢集解決方案 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的健康狀態檢測: 安裝配置方法: 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作為前端代理負載均衡成為越來越多架構師的首先方案。