nginx 學習筆記1

2022-07-18 03:06:13 字數 2381 閱讀 7779

感謝tengine團隊願意無私的分享他們所編寫的nginx學習書籍

眾所周知,nginx效能高,而nginx的高效能與其架構是分不開的。那麼nginx究竟是怎麼樣的呢?

我們可以看到,nginx是以多程序的方式來工作的,當然nginx也是支援多執行緒的方式的,只是主流的方式還是多程序的方式,也是nginx的預設方式。nginx的程序模型,可以由下圖來表示:

如果我們要操作nginx,只需要與master程序通訊就行了。aster程序會接收來自外界發來的訊號,再根據訊號做不同的事情。

乙個連線請求過來,每個程序都有可能處理這個連線,怎麼做到的呢?首先,每個worker程序都是從master程序fork過來,在master程序裡面,先建立好需要listen的socket(listenfd)之後,然後再fork出多個worker程序。所有worker程序的listenfd會在新連線到來時變得可讀,為保證只有乙個程序處理該連線,所有worker程序在註冊listenfd讀事件前搶accept_mutex,搶到互斥鎖的那個程序註冊listenfd讀事件,在讀事件裡呼叫accept接受該連線。當乙個worker程序在accept這個連線之後,就開始讀取請求,解析請求,處理請求,產生資料後,再返回給客戶端,最後才斷開連線,這樣乙個完整的請求就是這樣的了。我們可以看到,乙個請求,完全由worker程序來處理,而且只在乙個worker程序中處理。(跟我們這邊的**很像,我們這邊是抓拍時起八個執行緒搶,這邊是八個程序搶)。

nginx採用了非同步非阻塞的方式來處理請求,也就是說,nginx是可以同時處理成千上萬個請求的。

為什麼nginx可以採用非同步非阻塞的方式來處理呢,或者非同步非阻塞到底是怎麼回事呢?

我們先回到原點,看看乙個請求的完整過程。首先,請求過來,要建立連線,然後再接收資料,接收資料後,再傳送資料。具體到系統底層,就是讀寫事件,而當讀寫事件沒有準備好時,必然不可操作,如果不用非阻塞的方式來呼叫,那就得阻塞呼叫了,事件沒有準備好,那就只能等了,等事件準備好了,你再繼續吧。阻塞呼叫會進入核心等待,cpu就會讓出去給別人用了,對單執行緒的worker來說,顯然不合適,當網路事件越多時,大家都在等待呢,cpu空閒下來沒人用,cpu利用率自然上不去了,更別談高併發了。好吧,你說加程序數,這跟apache的執行緒模型有什麼區別,注意,別增加無謂的上下文切換。所以,在nginx裡面,最忌諱阻塞的系統呼叫了。不要阻塞,那就非阻塞嘍。非阻塞就是,事件沒有準備好,馬上返回eagain,告訴你,事件還沒準備好呢,你慌什麼,過會再來吧。好吧,你過一會,再來檢查一下事件,直到事件準備好了為止,在這期間,你就可以先去做其它事情,然後再來看看事件好了沒。雖然不阻塞了,但你得不時地過來檢查一下事件的狀態,你可以做更多的事情了,但帶來的開銷也是不小的。所以,才會有了非同步非阻塞的事件處理機制,具體到系統呼叫就是像select/poll/epoll/kqueue這樣的系統呼叫。它們提供了一種機制,讓你可以同時監控多個事件,呼叫他們是阻塞的,但可以設定超時時間,在超時時間之內,如果有事件準備好了,就返回。

執行緒只有乙個,所以同時能處理的請求當然只有乙個了,只是在請求間進行不斷地切換而已,切換也是因為非同步事件未準備好,而主動讓出的。這裡的切換是沒有任何代價,你可以理解為迴圈處理多個準備好的事件,事實上就是這樣的。與多執行緒相比,這種事件處理方式是有很大的優勢的,不需要建立執行緒,每個請求占用的記憶體也很少,沒有上下文切換,事件處理非常的輕量級。併發數再多也不會導致無謂的資源浪費(上下文切換)。更多的併發數,只是會占用更多的記憶體而已。 原文作者之前有對連線數進行過測試,在24g記憶體的機器上,處理的併發請求數達到過200萬。現在的網路伺服器基本都採用這種方式,這也是nginx效能高效的主要原因。

由於epoll_wait等函式在呼叫的時候是可以設定乙個超時時間的,所以nginx借助這個超時時間來實現定時器。nginx裡面的定時器事件是放在一顆維護定時器的紅黑樹裡面,每次在進入epoll_wait前,先從該紅黑樹裡面拿到所有定時器事件的最小時間,在計算出epoll_wait的超時時間後進入epoll_wait。所以,當沒有事件產生,也沒有中斷訊號時,epoll_wait會超時,也就是說,定時器事件到了。這時,nginx會檢查所有的超時事件,將他們的狀態設定為超時,然後再去處理網路事件。由此可以看出,當我們寫nginx**時,在處理網路事件的**函式時,通常做的第乙個事情就是判斷超時,然後再去處理網路事件。

用一段偽**來總結一下nginx的事件處理模型:

while (true)  else 

nevents = poll_function(events, timeout);

for i in nevents:

task t;

if (events[i].type == read) else

run_tasks_add(t);

}

Nginx學習筆記 1

nginx安裝 nginx 安裝目錄 drwxrwxr x 2 daxin daxin 4096 mar 9 17 50 conf 配置目錄 drwxr xr x.2 daxin daxin 4096 mar 9 17 50 html 存放靜態頁面的目錄 drwxrwxr x 2 daxin dax...

nginx學習筆記1 命令

nginx h 或 1 另行指定配置檔案的啟動方式 nginx c tmpnginx.conf,這時,會讀取 c引數後指定的nginx.conf配置檔案來啟動nginx。2 另行指定安裝目錄的啟動方式 nginx p usr local nginx 使用 p引數指定nginx的安裝目錄 3 另行指定...

nginx 學習筆記 1 nginx安裝

1.nginx安裝 根據作業系統的不同,nginx的安裝方式也不相同。1.1 對linux系統來說,nginx.org提供了nginx安裝包。目前,ngnix提供了如下版本的作業系統的安裝包 rhel centos version 5.x6.x debian version codename 6.x...