1. 程式人生 > 實用技巧 >Nginx高效的原因

Nginx高效的原因

導讀

研發同學們對應用過載就擴容這個動作已是非常的熟悉,但大家有聽說過業務流量突增,nginx也隨之需要擴容嘛?我相信很少聽過,為什麼呢?主要是nginx高效工作起作用,那接下來我們來講講我們nginx為何高效。

一. Nginx 為何神物

Nginx 是一種非同步框架的web伺服器,它可以用作反向代理、負載均衡器和 HTTP 快取或郵件伺服器。Nginx 是免費且開源的,根據類 BSD 許可證的條款釋出,意味任何人都可以下載甚至修改原始碼。Nginx 軟體由伊戈爾·賽索耶夫建立並於 2004 年首次公開發布。2011 年成立同名公司以提供支援,現大部分網際網路公司都在使用。早期我們公司使用的是 tengine+tengine-cgi+php-fpm 的架構來提供服務,後來公司統一使用dubbo後,我們架構升級為 TGW(tengine叢集)+tengine+java-cgi , 同時,我們的 Tengine+lua (nginx衍生版本) 還具備有 WAF防火牆,流量管控,流量排程,統一日誌和實時監控等的定製化開發模組。

二.Nginx 為何高效

一個高效能web伺服器典型特點是處理速度快且消耗資源少.尤其在上萬連線同時線上的時候.若要做到處理速度快,併發模型的設計尤其關鍵.伺服器併發量取決於兩個因素:一是伺服器連線的程序數量, 二是每個程序可同時處理的併發請求數量,因而web伺服器併發模型由兩部分構成,服務的提供方式和連線處理機制, 這兩種別具一格的方式使得Nginx在同類型的web伺服器中表現優秀。

1. 服務提供方式

一般Web伺服器併發處理請求有以下三種方式:多程序方式、多執行緒方式、非同步方式。

多程序需要記憶體複製等額外開銷,客戶端較多時候,伺服器效能會降低,典型應用如Apache的prefork模組;

多執行緒使用程序中多個執行緒提供服務,多執行緒開銷較小,典型應用如Apache的worker模組;

非同步則採用非阻塞的方式與每個客戶通訊,伺服器用一個程序進行輪詢,典型應用如Nginx的work process程序;

其中效率最高是非同步,最穩定是多程序、佔用資源少是多執行緒。

型別優點缺點
多程序方式 穩定性高:由於採用獨立程序處理獨立請求,而程序之間是獨立的,單個程序問題不會影響其他程序,因此穩定性最好 資源佔用率高:當請求過大時,需要大量的程序處理請求,程序生成、切換開銷很大,而且程序間資源是獨立的,造成記憶體重複利用。
多執行緒方式 開銷較小:執行緒間部分資料是共享的,且執行緒生成與執行緒間的切換所需資源開銷比程序間切換小得多
執行緒切換過快可能造成執行緒抖動,且執行緒過多會造成伺服器不穩定。
非同步方式 效能最好:一個程序或執行緒處理多個請求,不需要額外開銷,效能最好,資源佔用最低。 某個程序或執行緒出錯,可能導致大量請求無法處理,甚至導致整個服務宕機。

Nginx基於事件模型(非同步方式)提供服務,更適合每秒連線數和請求數同時非線性增長的情況。即使負載增加了,記憶體和CPU使用事件數量始終保持可預期。Nginx使用普通的硬體就能在一個伺服器上處理數萬的併發連線。這就是Nginx高效能的第一個原因。

2.連線處理機制

談到連線處理機制,關鍵是LINUX的I/O模型,同步阻塞io,同步非阻塞io,非同步阻塞io(io複用),非同步非阻塞io(訊號驅動或者非同步io)

阻塞和非阻塞:

那什麼是阻塞和非阻塞呢,這裡用點菜傳菜舉例來說明阻塞和非阻塞:

第一種:就在出菜視窗等待,直到廚師炒完菜後將菜送到視窗,然後服務員再將菜送到使用者手中;
第二種:等一會再到視窗來問廚師,某個菜好了沒?如果沒有先處理其他事情,等會再去問一次;

第一種為阻塞方式,第二種為非阻塞的。從上面看,明顯第二種非阻塞的效率更高;

同步和非同步:

那什麼是同步和非同步呢,這裡用傳菜來舉例下同步和非同步 :

同步:客戶點菜,服務員直接跟廚師打交道,菜出來沒出來,服務員直接指導,但只有當廚師將菜送到服務員手上,這個過程才算正常完成,這就是同步的事件。
非同步:同樣是點菜,有些餐館有專門的傳菜人員,當廚師炒好菜後,傳菜員將菜送到傳菜視窗,並通知服務員,這就變成非同步的了。

對於同步的事件,你只能以阻塞的方式去做。而對於非同步的事件,阻塞和非阻塞都是可以的,

傳統的伺服器採用的就是同步阻塞的多程序模型,而Nginx伺服器使用多程序機制能夠保證不增長對系統資源的壓力,同時使用非同步非阻塞方式減少了工作程序在I/O呼叫上的阻塞延遲,保證了不降低對請求的處理能力,這就是高效原因之一。

I/O多路複用:

select 和 poll 一般所有的作業系統都會支援,但是每次等待都要設定需要等待的套介面,並且內部的實現不夠高效,很難支援監聽高併發量的套介面集。不同的作業系統使用了不同的高階輪詢技術來支援高效能的監聽,一般這些方式都不是可移植的,比如freebsd上實現了 kqueue,solaris實現了/dev/poll,linux實現了epoll等。我們使用的 Centos 6.x 系統的epoll庫。這也就是Nginx高效能的第二大原因。

4. Tengine 豐富外掛

Tengine 是 nginx衍生版本,效能和穩定性已經在大型的網站如淘寶網,天貓商城等得到了很好的體驗,其一個重要特點就是非常多的豐富外掛,以下就來介紹下我們樂信使用了哪些 Tengine 外掛模組:

---with-http_concat_module\##用於合併多個檔案在一個響應報文中
---with-http_flv_module\##供服務端偽流媒體支援
---with-http_stub_status_module\##nginx效能監控
---with-http_gzip_static_module\##gzip支援各類資料壓縮傳輸,降低網路
---with-http_sysguard_module\##過載保護模組
---with-http_lua_module\##lua模組
---with-http_v2_module\##http2支援
---add-module=../nginx_upstream_check_module-master\##upstream健康檢測和自動剔除模組
---add-module=../nginx-upsync-module-1.8.x##實現配置動態更新等等;

正是以上tengine豐富的外掛,給我們的業務帶來了強穩定性,高併發效能噢;

5. tengine 其它特性

除了以上,內部有大量可見的細節優化,採用多程序單執行緒的工作方式,並且利用cpu和程序的親緣性將程序和特定cpu繫結(tengine預設支援),避免了程序上下文切換的開銷,從而減少了cpu佔用。另外它實現了高效的記憶體池,將記憶體佔用降到最低等,這個依靠於nginx.cong 主配置進行優化等等;

三. tengine 擴充套件 lua

ngx_lua 模組是 nginx 第三方模組,它能將lua語言嵌入到nginx配置中,從而使用lua 極大增強了nginx的能力,nginx以高併發而知名,lua指令碼輕便,兩者的搭配堪稱完美。

我們使用的 tengine+lua 大致可以分為2類作用,第一類是核心接入伺服器,第二類是業務承載伺服器,可能在我們這裡都統稱在一個大叢集裡面:

核心接入伺服器:
1.如動態負載均衡(後續我們需要做的,因為我們業務需更高級別隔離);
2.根據請求特徵將流量分配到不同分組不同set或者機房,我們叫它流量排程(已具備);
3.防DDOS攻擊限流:可以將請求日誌推送到實時計算叢集,然後將需要限流的IP推送到核心Nginx進行限流(我們利用TGW防DDOS攻擊);
4.快取服務,使用NginxProxyCache實現內容頁面的快取等等;
業務承載伺服器:
1.快取,直接把圖片等資源連結儲存在redis,通過lua+nginx+redis 進行第一層請求返回(如tab頁快取);
2.AB測試/灰度釋出:比如要上一個新的介面,可以通過在業務Nginx通過Lua寫複雜的業務規則實現不同的人看到不同的版本。(已具備);
3.服務質量監控:我們可以記錄請求響應時間、快取響應時間、反向代理服務響應時間等達到實時監控,另外記錄非200狀態碼錯誤來了監控服務可用率(已具備)等功能;

四. 總結

  1. nginx 它是一個高效能web伺服器,它能同時提供上萬的連線請求,而且速度快,佔用資源少,部署在普通伺服器就ok;

  2. nginx 高效是因為非同步且採用非阻塞的方式與每個客戶通訊,通過使用了作業系統IO複用方式(select和poll、epoll)達到高效能;

  3. tengine 豐富的外掛可提供我們插拔式選擇使用,並且在主配置檔案也具有大量的優化效能引數,如記憶體池,cpu親緣性繫結等等;

  4. lua_ngx 現在在我們業務方面實踐,比如有waf防火牆,流量排程,流量管控,頁面快取,質量監控,統一日誌等多個模組應用業務上。