nginx

(1)什麼是nginx?

nginx是:一個高性能的HTTP和反向代理服務器,用時也是一個ICMP/POP3/SMTP代理服務器。目前有很多國內網站採用nginx作爲web服務器。

(2)nginx特點

nginx以事件驅動的方式編寫,所以有非常好的性能,同時也是一個非常高效的反向代理,負載平衡
nginx作爲HTTP服務器,有以下特徵:

  • 處理靜態文件,索引文件以及自動索引;打開文件描述符緩衝。
  • 無緩存的反向代理加速器,簡單的負載均衡和容錯。
  • FastCGI,簡單的負載均衡和容錯。
  • 模塊化的結構。
  • 支持SSL和TLSSNI。

(3)nginx架構

nginx在啓動後,會有一個master進程和多個worker進行。master進程主要用來管理worker進程,包含:接收來自外界的信號,向各worker進程發送信號,監控worker進程的運行狀態,當worker進程退出後(異常情況下),會自動啓動新的worker進程。而基本的網絡事件則是放在worker進程中來處理。多個worker之間是對等的,他們同等競爭來字客戶端的請求,個=各進程之間是獨立的。一個請求,只可能在一個worker進程中處理,一個worker進程不可能處理其他進程的請求。worker進程的個數是可以設置的,一般設置的是與機器的CPU 核數一致。
如下圖示:nginx的進程模型

在nginx啓動之後,如果要操作nginx,可以通過master來管理worker進程,所以只需要與master通信即可,master會接收來自外界的信號,再根據信號做不同的事情。所以要控制nginx只需要通過kill向master進程發送信號即可。

  • 每個worker進程都是從master進程fork過來,在master進程裏面,先建立好需要listen的socket之後,然後再fork出多個worker進程。
  • 所有的worker進程的socket會在新連接到來之前時變得可讀,爲保證只有一個進程處理該連接,所有worker進程在註冊socket讀事件前搶先accept_mutex
  • 搶到互斥鎖的那個進程註冊socket讀事件,在讀事件裏調用accpet接收連接。
  • 當一個worker進程請求accpet這個連接之後,就開始讀取請求,解析請求,處理請求,產生數據之後,再返回給客戶端
  • 之後斷開連接

(4)nginx採用這種進程模型的優勢

  • 由於對於每個worker進程來說,獨立的進程,不需要加鎖,所以省掉了鎖帶來的開銷,同時在編程以及問題查找時,也很方便。
  • 採用獨立的進程,可以讓互相之間不會影響,一個進程退出後,其他進程還在工作,服務不會中斷,master進程則很快啓動新的worker進程。
  • worker進程的異常退出會導致當前worker上的所有請求失敗,不過不會影響到所有的請求,因此降低了風險。

(5)nginx事件處理機制

nginx採用了異步非阻塞的方式處理請求,可以同時監控多個事件,調用它們是阻塞的,但是可以設置超時時間,在超市時間內,如果有事件準備好了,就返回。
如:epoll爲例,在事件沒有準備好時,放到epoll裏,事件準備好了,我們就去讀寫,當讀寫返回eagain時,我們將它再次加入到epoll中,這樣,只有事件準備好了,我們纔會去處理它,只有當事件都沒有準備好,纔在epoll裏面等着。這樣就可以處理大量的未完成的併發請求。線程只有一個,所以同時處理的請求當然只有一個,只是在請求之間不斷切換而已,切換到的原因就是異步事件未準備好,而主動退出的,這裏的切換是沒有任何代價的。

(6)connection

nginx中的connection就是對tcp連接的封裝,其中包括連接的socket,讀事件,寫事件。利用nginx封裝的connection,我們可以很方便的使用nginx來處理與連接相關的事情,比如建立連接,發送與接收數據等。而nginx中的http請求的處理就是建立在connection之上的。

nginx_tcp(nginx如何處理一個tcp連接?)

nginx做服務器端

  • 首先在nginx啓動時,會解析配置文件,得到需要監聽的IP地址和端口,然後在nginx的master進程裏面,先初始化好這個監控的socket(包括創建socket,設置ddrreuse等選項,綁定到指定的IP地址和端口,再listen)。
  • 然後再fork出多個子進程出來,然後子進程會競爭accept新的連接。此時客戶端就可以向nginx發起連接了。
  • 當客戶端與服務器端通過三次握手建立好一個連接之後,nginx的某一個子進程會accpet成功,得到這個連接好的連接的socket,然後創建nginx對連接的封裝(即ngx_connetcion_t結構體)。
  • 之後設置讀寫事件處理函數並添加讀寫事件來與客戶端進行數據的交換。
  • 最後,nginx或客戶端來主動關閉連接。

nginx做客戶端

nginx也可以作爲客戶端來請求其它server的數據的。

  • 此時,與其他server 創建的連接也封裝在ngx_cnnection_t中。
  • 作爲客戶端nginx先獲取一個ngx_connection_t結構體,然後創建socket,並設置socket的屬性。
  • 然後再通過添加讀寫事件,調用connect/read/write來調用連接.
  • 最後關閉連接,並釋放ngx_connection_t.

(7)nginx進程連接數

nginx在實現的時候,是通過一個連接池來管理連接的,連接池的大小是worker_connections。這裏的連接池裏面保存的其實不是真實的連接,它只是一個work_connections大小的一個ngx_nonnections_t結構的數組。並且,nginx會通過一個鏈表free_connections來保存所有的空閒ngx_connection_t,每次獲取一個連接時,就從空閒鏈表中獲取一個,用完後,再放回空閒連接鏈表裏。
這裏worker_connections這個參數表示的是每個worker所能建立的最大值,所以,一個nginx所能建立的最大連接數是worker_connections * worker_processes,當然這裏說的是最大連接數,也是對於HTTP請求本地資源能夠支持的最大併發數量,而如果是HTTP最爲反向代理來說,最大併發數量應該是worker_connection * worker_processes/2。作爲反向代理服務器,每個併發會建立與客戶端的連接和後端的連接,會佔用兩個連接。

(8)nginx控制多進程間的連接平衡

nginx的處理得先打開一accept_mutex選項,此時只有獲得了accept_mutex的進程纔會添加accept事件,也就是說,nginx會控制進程是否添加accept事件。nginx使用一個叫ngx_accept_disabled的變量來控制是否去競爭accept_mutex鎖。

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