Nginx 是一個輕量級的HTTP 服務程序,相比其餘服務器程序如Apache,Nginx佔用內存少,穩定性高,併發處理能力強。同時Nginx 仍是一個反向代理服務程序,和郵件代理服務程序。Nginx具備豐富的模塊庫、靈活的配置、較低資源消耗等優勢。下面,咱們一塊兒深刻看一下Nginx的工做機制。nginx
咱們從如下幾個方面說明如下:服務器
基於上面提到技術,以及Nginx不少地方的優化,讓Nginx成爲最快的HTTP服務器。網絡
在Nginx的技術架構中,進程模型是相當重要的一部分。接下來,咱們一塊兒看看Nginx進程模型,以及它們的工做機制。架構
Linux 系統中,Nginx默認以守護進程daemon方式啓動,默認採用多進程方式。Nginx包括兩種類型的進程:
- Master 進程,數量只有一個,管理Nginx自己和Worker進程
- Worker 進程,數量通常和CPU核數相等,Nginx的全部請求處理,均是在Worker進程中完成併發
下面,咱們分別深刻看一下Master和Worker進程。異步
在Nginx啓動時,Master進程建立,主要負責初始化Nginx和相關模塊、fork Worker進程、接收處理外界信號等工做。socket
咱們經過kill命令發送信號給Nignx Master 進程,看看Master進程如何處理:模塊化
root@eg001:~# ps -ef | grep nginx | grep -v grep root 16533 1 0 Aug28 ? 00:00:00 nginx: master process nginx www-data 16534 16533 0 Aug28 ? 00:00:47 nginx: worker process www-data 16535 16533 0 Aug28 ? 00:00:51 nginx: worker process www-data 16536 16533 0 Aug28 ? 00:00:53 nginx: worker process www-data 16537 16533 0 Aug28 ? 00:00:51 nginx: worker process root@eg001:~# kill -HUP 16533 root@eg001:~# ps -ef | grep nginx | grep -v grep root 16533 1 0 Aug28 ? 00:00:00 nginx: master process nginx www-data 28194 16533 0 09:40 ? 00:00:00 nginx: worker process www-data 28195 16533 0 09:40 ? 00:00:00 nginx: worker process www-data 28196 16533 0 09:40 ? 00:00:00 nginx: worker process www-data 28197 16533 0 09:40 ? 00:00:00 nginx: worker process root@eg001:~#
分析流程:
- Master 進程接收到 HUP 信號
- Master 進程從新加載配置文件
- Master 進程啓動新的Worker進程
- Master 進程發送信號給Worker 進程
- 老的Worker進程再也不接收新的請求
- 老的Worker進程處理完當前請求,退出
- 至此,Nginx完成平滑重啓函數
注意:Nginx 0.8 版本之後,提供了 -s參數,用於管理Nginx服務的中止和重啓,注意line 11:性能
root@eg001:~# nginx -h nginx version: nginx/1.1.19 Usage: nginx [-?hvVtq] [-s signal] [-c filename] [-p prefix] [-g directives] Options: -?,-h : this help -v : show version and exit -V : show version and configure options then exit -t : test configuration and exit -q : suppress non-error messages during configuration testing -s signal : send signal to a master process: stop, quit, reopen, reload -p prefix : set prefix path (default: /etc/nginx/) -c filename : set configuration file (default: /etc/nginx/nginx.conf) -g directives : set global directives out of configuration file
Worker進程負責全部請求的處理工做,咱們經過一個HTTP請求,來梳理一下Worker的工做流程:
- 新的請求到來:全部的Work進程的listenfd都會變得可讀
- 竟搶互斥鎖:全部 Worker 進程在註冊listenfd讀事件前,要先搶accept_mutex
- 搶到互斥鎖的Worker,註冊listenfd讀事件,在事件中調用accept接受該鏈接
- 拿到請求後,Worker進程開始讀取請求,解析請求,處理請求,產生數據,再返回給客戶端
- Worker進程斷開鏈接
須要注意:一個HTTP請求,徹底由Worker進程處理,並且只在一個Worker中處理
對於每一個Worker 進程來講,獨立的進程,不須要加鎖,節約鎖致使的資源開銷;worker進程之間,互不干擾,平滑重啓就是很好的例子,服務不中斷。
Nginx 採用的是異步非阻塞事件處理機制,支持select/poll/epoll/kqueue 等等。Nginx 同時會監控多個事件,調用他們是阻塞的。可是調用有超時時間,在超時時間內,若是有事件準備好了,就返回,不然從新放入epoll中。當讀寫返回EAGAIN時,事件將會被再次放入epoll中。
處理線程只有一個,同時處理的請求也只有一個,所謂多請求併發,只是在不斷的切換請求而已。雖然是切換,但這種切換不涉及上下文切換,相比十分輕量。更多的併發,只是會佔用更多的內存。
進程相關的還有,信號和定時器,這部分另外單獨講解。
Nginx是模塊化架構的服務,豐富的模塊,鬆散耦合,也讓Nginx更增強大!我看看Nginx 都有哪些模塊
驚羣效應:
- 當內核 accept 一個鏈接時,會喚醒全部等待中的進程
- 但實際上只有一個進程能獲取鏈接,其餘的進程都是被無效喚醒的
- 因此 Nginx 採用了自有的一套 accept 加鎖機制,避免多個進程同時調用 accept
- Nginx 多進程的鎖在底層默認是經過 CPU 自旋鎖來實現。若是操做系統不支持自旋鎖,就採用文件鎖。