亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

首頁 慕課教程 Nginx 入門教程 Nginx 入門教程 20 Nginx 的基礎架構解析(上)

Nginx 的基礎架構解析(上)

1. Nginx 的進程模型

前面介紹 Nginx 時有介紹過 Nginx 的進程模型。Nginx 啟動時首先啟動一個 Master 進程,然后由 Master 進程啟動一個或者多個 Worker 子進程。Master 進程主要完成配置讀取,通過發送信號控制 Worker 進程的啟動和停止等,而 Worker 子進程是用來處理客戶端發來的 Http 請求,且Worker進程之間會通過共享內存進行通信。

1.1 worker 進程處理請求過程

假設 Nginx 啟動了多個 Worker 進程,并且在 Master 進程中通過 socket 套接字監聽80端口。
這些 Worker 進程 fork 自 Master 進程,然后每個worker進程都可以去 accept 這個監聽的 socket。 當一個連接進來后,所有在 accept 在這個 socket 上面的進程,都會收到消息,但是只有一個進程可以 accept 這個連接,其它的則 accept 失敗,這便是所謂的驚群現象。Nginx 處理這種情況的方式就是加鎖。有了鎖之后,在同一時刻,就只會有一個 Worker 進程在 accpet 連接,這樣就不會有驚群問題了。在 Worker 進程拿到 Http 請求后,就開始按照前面介紹的 11個階段處理該 Http 請求,最后返回響應結果并斷開連接。

1.2 Nginx 命令行的處理流程

最早我們學習了 Nginx 命令行操作,這些命令行操作都是給 Master 進程發信號,然后再由 Master 進程發送信號給 Worker 進程,從而達到控制 Worker 進程的目標。我們以 Nginx 的熱部署命令./nginx -s reload 來描述 Nginx 命令行的執行流程。具體過程如下:

  • 首先 Master 進程會檢查 nginx.conf 文件是否存在語法錯誤,并從中找到 nginx.pid 配置路徑(沒有配置會使用默認值)

  • reload 參數表示向 Master 進程發送 HUP 信號。Nginx 會根據會保存在 nginx.pid 文件中的值找到 Master 進程的 pid。如果 Nginx 進程沒有啟動,則沒有該 nginx.pid 文件,命令行會報錯;

# 在 Nginx 的配置文件中配置 nginx.pid 的保存路徑
[root@server sbin]# ./nginx -s reload
nginx: [error] open() "/root/nginx/logs/nginx.pid" failed (2: No such file or directory)
  • Master 進程打開新的監聽端口;

  • Master 進程用新配置啟動新的 Worker 進程。新的 Worker 進程起來后,開始接收 Http 請求并處理,此時老的 Worker進程會停止接受 Http 請求;

  • Master 進程會向老的 Worker進程發送 QUIT 信號;

  • 老的 Worker 進程關閉監聽句柄,處理完正在進行的請求后結束進程。

Nginx 命令行中 -s 參數的每個值都對應這一個信號。因此,我們也可以直接對 Master 進程發生相應信號達到同樣的目的。

# pid表示Nginx的主進程id號
# kill -s 信號 pid

2. Nginx的事件驅動模型

2.1 事件驅動模型

事件驅動模型是實現異步非阻塞的一個手段。對于 web 服務器來說,客戶端 A 的請求連接到服務端時,服務端的某個進程(Nginx 的 worker 進程)會處理該請求,此進程在沒有返回給客戶端 A 結果時,它又去處理了客戶端 B 的請求。服務端把客戶端 A 以及客戶端 B 發來的請求作為事件交給了"事件收集器",而"事件收集器"再把收集到的事件交由"事件發送器"發送給"事件處理器"進行處理。最后"事件處理器"處理完該事件后,通知服務端進程,服務端進程再把結果返回給客戶端A、客戶端B。在這個過程中,服務端進程做的事情屬于用戶級別的,而事件處理這部分工作屬于內核級別的。也就是說這個事件驅動模型是需要操作系統內核來作為支撐的。

2.2 Nginx的事件驅動模型介紹

Nginx 的事件驅動模型,支持 select、poll、epoll、rtsig、kqueue、/dev/poll、eventport 等。
最常用的是前三種,特別是 epoll 模型,這也是 Nginx 中的默認配置??梢哉f epoll 模型成就了 Nginx 的高性能和高并發特性。

  • select模型:
    • 創建所關注事件的描述符集合,對于一個描述符,可以關注其上面的讀(Read)事件、寫(Write)事件以及異常發生(Exception)事件。
      在select模型中,要創建這3類事件描述符集合。
    • 調用底層提供的select()函數,等待事件發生。
    • 輪詢所有事件描述符集合中的每一個事件描述符,檢查是否有相應的事件發生,如果有就進行處理。
  • poll模型:
    • poll模型是Linux平臺上的事件驅動模型,在Linux2.1.23中引入的,Windows平臺不支持該模型。
    • poll模型和select模型工作方式基本相同,區別在于,select模型創建了3個描述符集合,而poll模型只創建一個描述符集合。
  • epoll模型:
    • epoll模型屬于poll模型的變種,在Linux2.5.44中引入。epoll比poll更加高效,原因在于它不需要輪詢整個描述符集合,而是Linux內核會關注事件集合,當有變動時,內核會發來通知。
    • 正式這種異步,非阻塞、IO多路復用的事件驅動模型,才使得 Nginx 有很高的運行效率。

3. 案例

3.1 Nginx 進程模型實驗

按照前面的講解,我們測試給 Nginx 的 Master 進程直接發送信號,并觀察進程情況:

# 確認沒有 Nginx 進程
[root@server sbin]# ps -ef | grep nginx
root     10603 10137  0 14:23 pts/2    00:00:00 grep --color=auto nginx
# 啟動 Nginx 
[root@server sbin]# ./nginx
# 可以看到 Nginx 啟動的進程
[root@server sbin]# ps -ef | grep nginx
root     10640     1  0 14:23 ?        00:00:00 nginx: master process ./nginx
root     10642 10640  0 14:23 ?        00:00:00 nginx: worker process
root     10643 10640  0 14:23 ?        00:00:00 nginx: worker process
root     10644 10640  0 14:23 ?        00:00:00 nginx: cache manager process
root     10645 10640  0 14:23 ?        00:00:00 nginx: cache loader process

可以看到 Nginx 啟動了 Master 進程(pid=10640),后由 Master 進程 fork 除了兩個 Worker 進程和兩個 Cache 進程,他們的父進程 id 均為10640?,F在做如下幾個操作:

  • 關閉進程號等于10642的 Worker 進程
[root@server sbin]# sudo kill -SIGTERM 10642
[root@server sbin]# ps -ef | grep nginx
root     10640     1  0 14:23 ?        00:00:00 nginx: master process ./nginx
root     10643 10640  0 14:23 ?        00:00:00 nginx: worker process
root     10644 10640  0 14:23 ?        00:00:00 nginx: cache manager process
root     10869 10640  0 14:32 ?        00:00:00 nginx: worker process
root     10939 10137  0 14:32 pts/2    00:00:00 grep --color=auto nginx

可以看到原先的 Worker 進程被殺死后,Nginx 的主進程又立馬拉起來一個新的 Worker 進程提供服務。這說明 Nginx 是非常可靠的,只要 Master 進程還在就會保證 Worker 進程持續存在并提供服務。

  • 向主進程發送 SIGHUP 信號,等價于 -s reload 操作??梢钥吹匠?Master 進程外,所有其他進程已經是新啟動的進程了。
[root@server sbin]# sudo kill -SIGHUP 10640
[root@server sbin]# ps -ef | grep nginx
root     10640     1  0 14:23 ?        00:00:00 nginx: master process ./nginx
root     11059 10640  0 14:37 ?        00:00:00 nginx: worker process
root     11060 10640  0 14:37 ?        00:00:00 nginx: worker process
root     11061 10640  0 14:37 ?        00:00:00 nginx: cache manager process
root     11098 10137  0 14:37 pts/2    00:00:00 grep --color=auto nginx
  • 向主進程發生 SIGTERM 信號,等價于 -s stop 操作,即停止 Nginx 服務,關閉所有進程
[root@server sbin]# sudo kill -SIGTERM 10640
[root@server sbin]# ps -ef | grep nginx
root     11267 10137  0 14:43 pts/2    00:00:00 grep --color=auto nginx
  • 向主進程發生 USR1 信號,等價于 -s repoen 操作,即重新打開日志文件
[root@server sbin]# ./nginx

[root@server sbin]# ps -ef | grep nginx
root     11408     1  0 14:48 ?        00:00:00 nginx: master process ./nginx
root     11410 11408  0 14:48 ?        00:00:00 nginx: worker process
root     11411 11408  0 14:48 ?        00:00:00 nginx: worker process
root     11412 11408  0 14:48 ?        00:00:00 nginx: cache manager process
root     11413 11408  0 14:48 ?        00:00:00 nginx: cache loader process
root     11484 10137  0 14:49 pts/2    00:00:00 grep --color=auto nginx

[root@server sbin]# ll ../logs/access.log 
-rw-r--r-- 1 root root 384349 Feb 11 14:26 ../logs/access.log

[root@server sbin]# rm -rf ../logs/access.log 

[root@server sbin]# ll ../logs/access.log 
ls: cannot access ../logs/access.log: No such file or directory

[root@server sbin]# kill -USR1 11408
[root@server sbin]# ll ../logs/access.log 
-rw-r--r-- 1 root root 0 Feb 11 14:50 ../logs/access.log

可以看到,在移除 Nginx 的 access.log 日志后,在向 Nginx 主進程發送 USR1 信號,Nginx 會重新生成一個新的 access.log 日志。

4. 小結

本節主要介紹 Nginx 的進程模型以及介紹了 Master 和 Worker 之間的通信過程。此外,我們介紹了 Nginx 的事件驅動模型。異步、多路IO復用、非阻塞等特點早就了 Nginx 的高性能。接下來,我們完成了 Nginx 進程模型的幾個實驗,直觀體檢 Nginx 的進程模型。下一節將重點介紹 Nginx 模塊相關的內容,并手動實現一個簡單的 http 模塊。