【深入理解Nginx】Nginx設計中的性能優化點

Nginx設計中的性能優化點

目錄

Nginx設計中的性能優化點

1、和nginx有關的內核性能調優

2、Nginx爲訪問第三方服務做的優化

3、內存池技術

4、事件

5、進程模型


1、和nginx有關的內核性能調優

2、Nginx爲訪問第三方服務做的優化

Nginx請求執行過程分析:

server模塊:是http模塊中的一個子模塊,用來定義一個虛擬訪問主機,也就是一個虛擬服務器的配置信息

location模塊:用於進行訪問路由的配置,主要用於配置路由信息在路由訪問配置中關聯到反向代理、負載均衡等各項功能。

upstream模塊:主要負責負載均衡的配置,通過默認的輪詢調度方式來分發請求到後端服務器。 

server模塊通過hash表搜索

支持通配符的hash表,爲了處理帶有通配符的域名字符串的匹配,實現了支持通配符的hash表nginx中的通配符有兩種形式:一種是通配符在前面的,例如*.test.com:可以省略*號,寫成.test.com;還有一種通配符在後面的例如 www.test.*,這樣域名不能省略 *號,注意:nginx不能同時包含在前面和在後的通配符例如 *.test.*。

將key字符串以 . 爲分隔符拆分成多個key字段,將所有key字符串的第一個key字段去重後存到一個基本hash表中,再將所有有相同的第一個key字段的字符串去掉第一個key字段後分別遞歸處理。 

location模塊通過二叉樹搜索

location塊通過二叉樹搜索,因爲是靜態的,不會變,所以不用紅黑樹,用的完全平衡二叉樹。 

upstream

(1)客戶端到nginx,nginx再到服務器端,網速是極不對稱的,反向代理的一個重要功能就是,提供大內存和磁盤文件緩存包,按照一定策略,接受完一定大小的包後,再由nginx發給客戶端或服務器端。這樣減少了服務器端需要維持的連接和緩存的佔用時間;

(2)與服務器端:1)建立tcp連接三次握手是異步的,發送syn後epoll註冊事件監聽,設置回調函數;2)向上遊發送請求或者接受下游請求,請求大小未知,所以發送請求的方法需要被epoll調度多次後才能發/收完請求的全部內容;3)包頭大小有一個合理範圍,而包體不一定,並且nginx不關心包體內容,因此nginx將包體頭部全部用內存緩存,包體則根據情況而定,透傳請求:nginx將客戶端的請求包體全部接受完後纔會發送給服務器端;4)透傳響應:不實現反向代理、轉發響應時上游網速優先,若下游網速快於上游網速,或者相差不大,不需要nginx開闢大塊內存或磁盤文件來緩存上游響應、轉發響應時下游網速優先,開闢內存和磁盤緩存響應。 

3、內存池技術

     Nginx爲每一個層級都會創建一個內存池,進行內存管理,比如一個模板,tcp連接,http請求等,在對應的生命週期結束的時候會摧毀整個內存池,把分配的內存一次性歸還給操作系統。在分配的內存上,nginx有小塊內存和大塊內存的概念,小塊內存nginx在分配的時候會嘗試在當前的內存池節點中分配,而大塊內存會調用系統函數malloc向操作系統申請。在釋放內存的時候,nginx沒有專門提供對釋放小塊內存的函數,小塊內存會在ngx_destory_pool和ngx_reset_pool的時候一併釋放。區分小塊內存和大塊內存的原因有兩個:1)針對大塊內存,如果它的生命週期遠遠短於所屬的內存池,那麼單獨提供一個釋放函數是十分有意義的;2)大塊內存與小塊內存的界限是一頁內存,大於一頁內存在物理上不一定是連續的,所以如果分配的內存大於一頁的話,從內存池中使用,和向操作系統重新申請效率差不多是等價的。

        還能夠對外部資源進行管理,能夠記錄日誌。

  • 用於減少系統調用次數;
  • 開發者申請一個內存池後可以任意從中申請內存,最後用完銷燬內存池即可。nginx是一個web服務器,每一個請求的生命週期很短,也決定了每個內存池的生命週期很短,因此不會累計過多沒有銷燬的內存池。而在開發模塊時,直接使用ngx_poll_t即可,模塊結束後自動釋放;
  • 申請大內存和小內存的不同處理:當nginx判斷申請內存大的時候,直接從堆上申請內存,掛到一個大內存鏈表上,大內存的生命週期可能遠遠小於請求的生命週期的情況,nginx提供了方法提前釋放而不用等到內存池銷燬,小塊內存nginx會一次申請比較大的一塊,後面複用;
  • 內存對齊,碎片整理。

4、事件

(1)網絡事件:epoll

(2)定時事件:紅黑樹實現,按照每個任務的時間來排序,每次取最左邊的節點時間和當前時間判斷即可,調用ngx_event_expire_timers方法觸發所有超時事件

(3)磁盤事件:nginx的讀操作作用的是linux內核實現,只有在內核進程完成了磁盤操作,內核纔會通知nginx進程。好處是一方面可以讓ngix更充分佔用CPU,另一方面當有大量讀磁盤的事件堆積到內核的時候,內核可以通過“電梯算法”降低隨機讀磁盤的成本。

5、進程模型

(1)master_worker:nginx啓動時master進程進行初始化讀取配置文件後fork出worker進程來監聽處理網絡事件,因爲是fork出來的,所以和master監聽的是同一個端口,accept事件到來時會有爭取。

1)master進程不負責網絡事件的監聽和處理,主要負責啓動服務,平滑升級,更換日誌文件,熱更新配置等,管理worker等功能。通過信號來管理worker進程;

2)worker進程監聽和處理網絡事件,一個worker掛了時master會快速拉起一個新的worker;

3)一個優化,nginx通常線程數和核心數相當,可以配置進程綁定CPU,減少進程在CPU間的躍遷,高效利用CPU cache。

(2)驚羣問題:nginx會fork多個子進程監聽同一個端口,子進程在accept建立新連接時會爭搶,進程數量多時會有性能下降,開accept_mutex鎖(默認打開)解決。nginx通過一個進程間同步鎖accept_mutex,保證同一時刻只能由一個worker在監聽web端口,釋放鎖通過定時器事件來實現。

(3)進程間負載均衡問題:多個worker搶一個事件時,會有一個成功,但如果這個worker本來就已經堆積了大量事件,另外有空間進程或者任務少的進程搶不到事件,子進程就會出現了負載不均衡。開accept_mutex鎖解決,每個worker有個變量ngx_accept_disabled,初始爲負值,絕對值爲配置的總連接數的7/8,每次使用一個連接就加1,這個值爲正時觸發負載均衡,此時accept事件時此worker不會去搶accept_mutex,而是將ngx_accept_disabled減一。

 

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