結合proxy和upstream子產品實作nginx負載均衡
結合<code>nginx_upstream_check_module</code>子產品實作後端伺服器的健康檢查
使用<code>nginx-sticky-module</code>擴充子產品實作cookie會話黏貼(session-sticky效果)
使用proxy子產品實作靜态檔案緩存
使用<code>ngx_cache_purge</code>實作更強大的緩存清除功能
上面提到的3個子產品都屬于第三方擴充子產品,需要提前下好源碼,然後編譯時通過<code>--add-moudle=src_path</code>一起安裝。
注意:
使用 nginx_upstream_check_module(簡記為m1) 時要先為nginx打上相應版本的patch,我的nginx版本為 1.6.3,是以patch對應 m1 解壓後目錄下的<code>check_1.5.12+.patch</code>,是以進入nginx源碼目錄,執行 patch -p1 ...(見下方示例)
nginx-sticky-module-ng(簡記為m2) 子產品可以單獨使用,但是因為m1監控檢查的方式是依賴于m2的,是以要使用m2,還要對m1打上patch,進入m2源碼目錄,執行 patch -p0...
編譯示例:(centos 6.5 x86_64, nginx 1.6.3)
如果你想在已安裝好的nginx上添加第三方子產品,依然需要重新編譯,但為了不覆寫你原有的配置,請不要make install,而是直接拷貝可執行檔案:
這個子產品的作用是通過cookie黏貼的方式将來自同一個用戶端(浏覽器)的請求發送到同一個後端伺服器上處理,這樣一定程度上可以解決多個backend servers的session同步的問題 —— 因為不再需要同步,而rr輪詢模式必須要運維人員自己考慮session同步的實作。
另外内置的 ip_hash 也可以實作根據用戶端ip來分發請求,但它很容易造成負載不均衡的情況,而如果nginx前面有cdn網絡或者來自同一區域網路的通路,它接收的用戶端ip是一樣的,容易造成負載不均衡現象。淘寶tengine的 ngx_http_upstream_session_sticky_module 也是類似的功能。nginx-sticky-module的cookie過期時間,預設浏覽器關閉就過期,也就是會話方式。
這個子產品并不合适不支援 cookie 或手動禁用了cookie的浏覽器,此時預設sticky就會切換成rr。它不能與ip_hash同時使用。
配置起來超級簡單,一般來說一個<code>sticky</code>指令就夠了。
<code>sticky [name=route] [domain=.foo.bar] [path=/] [expires=1h] [hash=index|md5|sha1] [no_fallback];</code>:
<code>name</code>: 可以為任何的 string 字元,預設是 route
<code>domain</code>:哪些域名下可以使用這個 cookie
<code>path</code>:哪些路徑對啟用 sticky,例如 path/test,那麼隻有 test 這個目錄才會使用 sticky 做負載均衡
<code>expires</code>:cookie 過期時間,預設浏覽器關閉就過期,也就是會話方式。
<code>no_fallbackup</code>:如果設定了這個,cookie 對應的伺服器當機了,那麼将會傳回502(bad gateway 或者 proxy error),建議不啟用
這裡順帶介紹一下nginx的負載均衡子產品支援的其它排程算法:
<code>輪詢</code>(預設) : 每個請求按時間順序逐一配置設定到不同的後端伺服器,如果後端某台伺服器當機,故障系統被自動剔除,使使用者通路不受影響。weight 指定輪詢權值,weight值越大,配置設定到的通路機率越高,主要用于後端每個伺服器性能不均的情況下。
<code>ip_hash</code> : 每個請求按通路ip的hash結果配置設定,這樣來自同一個ip的訪客固定通路一個後端伺服器,有效解決了動态網頁存在的session共享問題。當然如果這個節點不可用了,會發到下個節點,而此時沒有session同步的話就登出掉了。
<code>least_conn</code> : 請求被發送到目前活躍連接配接最少的realserver上。會考慮weight的值。
<code>url_hash</code> : 此方法按通路url的hash結果來配置設定請求,使每個url定向到同一個後端伺服器,可以進一步提高後端緩存伺服器的效率。nginx本身是不支援url_hash的,如果需要使用這種排程算法,必須安裝nginx 的hash軟體包 nginx_upstream_hash 。
<code>fair</code> : 這是比上面兩個更加智能的負載均衡算法。此種算法可以依據頁面大小和加載時間長短智能地進行負載均衡,也就是根據後端伺服器的響應時間來配置設定請求,響應時間短的優先配置設定。nginx本身是不支援fair的,如果需要使用這種排程算法,必須下載下傳nginx的 upstream_fair 子產品。
嚴格來說,nginx自帶是沒有針對負載均衡後端節點的健康檢查的,但是可以通過預設自帶的 ngx_http_proxy_module 子產品和 ngx_http_upstream_module 子產品中的相關指令來完成當後端節點出現故障時,自動切換到下一個節點來提供通路。
<code>weight</code> : 輪詢權值也是可以用在ip_hash的,預設值為1
<code>max_fails</code> : 允許請求失敗的次數,預設為1。當超過最大次數時,傳回proxy_next_upstream 子產品定義的錯誤。
<code>fail_timeout</code> : 有兩層含義,一是在 30s 時間内最多容許 2 次失敗;二是在經曆了 2 次失敗以後,30s時間内不配置設定請求到這台伺服器。
<code>backup</code> : 預留的備份機器。當其他所有的非backup機器出現故障的時候,才會請求backup機器,是以這台機器的壓力最輕。(為什麼我的1.6.3版本裡配置backup啟動nginx時說<code>invalid parameter "backup"</code>?)
<code>max_conns</code>: 限制同時連接配接到某台後端伺服器的連接配接數,預設為0即無限制。因為<code>queue</code>指令是commercial,是以還是保持預設吧。
<code>proxy_next_upstream</code> : 這個指令屬于 http_proxy 子產品的,指定後端傳回什麼樣的異常響應時,使用另一個realserver
下面的是一個帶後端監控檢查的 nginx.conf 配置:
上面配置的意思是,對name這個負載均衡條目中的所有節點,每個5秒檢測一次,請求2次正常則标記 realserver狀态為up,如果檢測 3 次都失敗,則标記 realserver的狀态為down,逾時時間為1秒。
check指令隻能出現在upstream中:
<code>interval</code> : 向後端發送的健康檢查包的間隔。
<code>fall</code> : 如果連續失敗次數達到fall_count,伺服器就被認為是down。
<code>rise</code> : 如果連續成功次數達到rise_count,伺服器就被認為是up。
<code>timeout</code> : 後端健康請求的逾時時間。
<code>default_down</code> : 設定初始時伺服器的狀态,如果是true,就說明預設是down的,如果是false,就是up的。預設值是true,也就是一開始伺服器認為是不可用,要等健康檢查包達到一定成功次數以後才會被認為是健康的。
<code>type</code>:健康檢查包的類型,現在支援以下多種類型
<code>tcp</code>:簡單的tcp連接配接,如果連接配接成功,就說明後端正常。
<code>http</code>:發送http請求,通過後端的回複包的狀态來判斷後端是否存活。
<code>ajp</code>:向後端發送ajp協定的cping包,通過接收cpong包來判斷後端是否存活。
<code>ssl_hello</code>:發送一個初始的ssl hello包并接受伺服器的ssl hello包。
<code>mysql</code>: 向mysql伺服器連接配接,通過接收伺服器的greeting包來判斷後端是否存活。
<code>fastcgi</code>:發送一個fastcgi請求,通過接受解析fastcgi響應來判斷後端是否存活
<code>port</code>: 指定後端伺服器的檢查端口。你可以指定不同于真實服務的後端伺服器的端口,比如後端提供的是443端口的應用,你可以去檢查80端口的狀态來判斷後端健康狀況。預設是0,表示跟後端server提供真實服務的端口一樣。該選項出現于tengine-1.4.0。
如果 type 為 http ,你還可以使用<code>check_http_send</code>來配置http監控檢查包發送的請求内容,為了減少傳輸資料量,推薦采用 head 方法。當采用長連接配接進行健康檢查時,需在該指令中添加keep-alive請求頭,如: <code>head / http/1.1\r\nconnection: keep-alive\r\n\r\n</code> 。當采用 get 方法的情況下,請求uri的size不宜過大,確定可以在1個interval内傳輸完成,否則會被健康檢查子產品視為後端伺服器或網絡異常。
<code>check_http_expect_alive</code>指定http回複的成功狀态,預設認為 2xx 和 3xx 的狀态是健康的。
nginx的頁面緩存功能與上面的負載均衡和健康檢查是沒有關系的,放在這裡一是因為懶得再起一篇文章,二是再有load-balance的地方一般都會啟用緩存的。
說明
<code>proxy_temp_path</code> : 緩存臨時目錄。後端的響應并不直接傳回用戶端,而是先寫到一個臨時檔案中,然後被rename一下當做緩存放在 proxy_cache_path 。0.8.9版本以後允許temp和cache兩個目錄在不同檔案系統上(分區),然而為了減少性能損失還是建議把它們設成一個檔案系統上。
<code>proxy_cache_path ...</code> : 設定緩存目錄,目錄裡的檔案名是 cache_key 的md5值。
<code>levels=1:2 keys_zone=cache_one:50m</code>表示采用2級目錄結構,web緩存區名稱為cache_one,記憶體緩存空間大小為100mb,這個緩沖zone可以被多次使用。檔案系統上看到的緩存檔案名類似于 /usr/local/nginx-1.6/proxy_cache/c/29/b7f54b2df7773722d382f4809d65029c 。
<code>inactive=2d max_size=2g</code>表示2天沒有被通路的内容自動清除,硬碟最大緩存空間為2gb,超過這個大學将清除最近最少使用的資料。
<code>proxy_cache</code> : 引用前面定義的緩存區 cache_one
<code>proxy_cache_key</code> : 定義cache_key
<code>proxy_cache_valid</code> : 為不同的響應狀态碼設定不同的緩存時間,比如200、302等正常結果可以緩存的時間長點,而404、500等緩存時間設定短一些,這個時間到了檔案就會過期,而不論是否剛被通路過。
<code>expires</code> : 在響應頭裡設定<code>expires:</code>或<code>cache-control:max-age</code>,傳回給用戶端的浏覽器緩存失效時間。
使用 ngx_cache_purge 子產品清除緩存有2種辦法(直接删除緩存目錄下的檔案也算一種辦法):
echo發送purge指令
<code>proxy_cache_purge purge from 127.0.0.1</code>表示隻允許在來自本地的清除指令
get方式請求url
即使用配置檔案中的<code>location ~ /purge(/.*)</code>,浏覽器通路<code>http://ittest.example.com/purge/your/may/path</code>來清除緩存,或者<code>echo -e 'get /purge/ http/1.0\r\n' | nc ittest.example.com 80</code>