Nginx 進程結構 這篇文章我們來看下 Nginx 的進程結構,Nginx 其實有兩種進程結構: 單進程結構 多進程結構 單進程結構實際上不適用於生產環境,只適合我們做開發調試使用。因為在生產環境中我們必須保持 Nginx 足夠健壯以及 Nginx 可以利用多核的一個特性,而單進程的 Nginx ...
Nginx 進程結構
這篇文章我們來看下 Nginx 的進程結構,Nginx 其實有兩種進程結構:
- 單進程結構
- 多進程結構
單進程結構實際上不適用於生產環境,只適合我們做開發調試使用。因為在生產環境中我們必須保持 Nginx 足夠健壯以及 Nginx 可以利用多核的一個特性,而單進程的 Nginx 是做不到這一點的,所以預設的配置中都是打開為多進程的 Nginx。
我們來看一下,多進程的 Nginx 結構中它的進程模型是怎樣的。
多進程中的 Nginx 進程架構如下圖所示,會有一個父進程(Master Process),它會有很多子進程(Child Processes),這些子進程會分為兩類:
- worker 進程
- cache 相關的進程
為什麼 Nginx 採用多進程結構而不是多線程結構呢?
因為 Nginx 最核心的一個目的是要保持高可用性、高可靠性,而當 Nginx 如果使用的是多線程結構的時候,因為線程之間是共用同一個地址空間的,所以當某一個第三方模塊引發了一個地址空間導致的段錯誤時、在地址越界出現時,會導致整個 Nginx 進程全部掛掉。而當採用多進程模型時,往往不會出現這樣的問題。從上圖可以看到 Nginx 在做進程設計時,同樣遵循了實現高可用、高可靠這樣的一個目的。
比如說在 master 進程中,通常第三方模塊是不會在 master 部分加入自己的功能代碼的。雖然 Nginx 在設計時,允許第三方模塊在 master 進程中添加自己獨有的、自定義的一些方法,但是通常沒有第三方模塊這麼做。
master 進程被設計用來的目的是做 worker 進程的管理的,也就是所有的 worker 進程是處理真正的請求的,而 master 進程負責監控每個 worker 進程是不是在正常的工作、需不需要做重新載入配置文件、需不需要做熱部署。
而 cache (緩存)是在多個 worker 進程間共用的,而且緩存不僅要被 worker 進程使用,還要被 cache manager 和 cache loader進程 使用。cache manager 和 cache loader 也是為反向代理時,後端發來的動態請求做緩存所使用的,cache loader 只是用來做緩存的載入、cache manager 用來做緩存的管理。實際上每個請求處理時,使用到緩存還是由 worker 進程來進行的。
這些進程間的通訊,都是使用共用記憶體來解決的。可以看到cache manager 和 cache loader各有一個進程,master 進程因為是父進程,所以肯定只有一個。那麼 worker 進程為什麼會有很多呢?這是因為 Nginx 採用了事件驅動引擎以後,他希望每一個 worker 進程從頭到尾占有一顆CPU,所以往往不止要把 worker 進程的數量配置與我們伺服器上的 CPU核數一致以外,還需要把每一個worker進程與某一顆CPU核綁定在一起,這樣可以更好的使用每顆CPU核上面的CPU緩存來減少緩存失效的命中率。
以上就是 Nginx 的進程結構的介紹,瞭解這些後更有助於我們去配置 Nginx。
剛纔我們介紹了 Nginx 使用了多進程模型,由 master 作為父進程啟動許多子進程,也知道了 Nginx 父子進程之間是通過信號來管理的,接下來通過一個實例給大家直觀的看下父子進程以及信號之間是如何工作的。
Nginx 的進程結構實例
首先啟動 Nginx,併在 Nginx 中啟動了兩個 worker 進程,通過 ps 命令可以看到當前進程 PID 和父進程 PID,有一個 nginx master 進程是由 root 用戶起的,進程 PID 是 2368。還有兩個 worker 進程和 cache 進程,它們是由 2368 進程起來的。它們的進程 PID 分別為 8652,8653,8655。
現在我們使用 ./sbin/nginx -s reload
命令,會把之前的 worker 進程和 cache 進程優雅的退出,然後再使用的新的配置項啟動新的 worker 進程,這裡我們並沒有改變配置,但是我們可以看到老的三個子進程會退出,並生成新的子進程。
可以看到,之前的三個子進程,現在已經都不在了,反而由 2368 新起了 8657,8658,8660 三個子進程。
[root@wupx nginx]# ps -ef|grep nginx
root 2368 1 0 Sep21 ? 00:00:00 nginx: master process /usr/sbin/nginx
root 4751 4688 0 11:41 pts/0 00:00:00 grep --color=auto nginx
nginx 8652 2368 0 Nov12 ? 00:00:00 nginx: worker process
nginx 8653 2368 0 Nov12 ? 00:00:00 nginx: worker process
nginx 8655 2368 0 Nov12 ? 00:00:00 nginx: cache manager process
[root@wupx nginx]# ./sbin/nginx -s reload
[root@wupx nginx]# ps -ef|grep nginx
root 2368 1 0 Sep21 ? 00:00:00 nginx: master process /usr/sbin/nginx
root 4753 4688 0 11:43 pts/0 00:00:00 grep --color=auto nginx
nginx 8657 2368 0 Nov12 ? 00:00:00 nginx: worker process
nginx 8658 2368 0 Nov12 ? 00:00:00 nginx: worker process
nginx 8660 2368 0 Nov12 ? 00:00:00 nginx: cache manager process
執行命令之後可以看到 worker 的 PID 已經變化了(之前講過 ./sbin/nginx -s reload
跟 kill -SIGHUP
作用是一樣的。)。
kill -SIGTERM
是向現有的 worker 進程發送退出的信號,對應的 worker 進程就會退出;進程在退出時,會自動向父進程 master 發送一個退出信號,master 就知道他的子進程退出了,然後新起一個 worker 進程。
[root@wupx nginx]# ps -ef|grep nginx
root 2368 1 0 Sep21 ? 00:00:00 nginx: master process /usr/sbin/nginx
root 4753 4688 0 11:43 pts/0 00:00:00 grep --color=auto nginx
nginx 8657 2368 0 Nov12 ? 00:00:00 nginx: worker process
nginx 8658 2368 0 Nov12 ? 00:00:00 nginx: worker process
nginx 8660 2368 0 Nov12 ? 00:00:00 nginx: cache manager process
[root@wupx nginx]# kill -SIGTERM 8658
[root@wupx nginx]# ps -ef|grep nginx
root 2368 1 0 Sep21 ? 00:00:00 nginx: master process /usr/sbin/nginx
root 4753 4688 0 11:44 pts/0 00:00:00 grep --color=auto nginx
nginx 8657 2368 0 Nov12 ? 00:00:00 nginx: worker process
nginx 8660 2368 0 Nov12 ? 00:00:00 nginx: cache manager process
nginx 8663 2368 0 Nov12 ? 00:00:00 nginx: worker process
通過實例演示,我們可以看到 Nginx 的進程結構以及 Nginx 使用信號的方式,其實命令行中的許多子命令就是再向 master 進程發送信號而已。