當前位置:首頁 >教程首頁 > IT 學院 > WEB前端+全棧工程師班 >超級幹貨!詳細解讀NGINX

超級幹貨!詳細解讀NGINX

發布時間:2019-04-22 10:29:56

從事前端工作,各種服務器的掌握是必不可少的,比如NGINX,那什麼是NGINX呢?今天就給大家詳細解讀NGINX!

1.jpg

什麼是Nginx代理服務器?

代理服務器:一般是指局域網內部的機器通過代理服務器發送請求到互聯網上的服務器,代理服務器一般作用在客戶端。應用比如:GoAgent。

2.jpg

一個完整的代理請求過程為:首先客戶端與代理服務器創建連接,接著根據代理服務器所使用的代理協議,請求對目標服務器創建連接、或者獲得目標服務器的指定資源。Web代理(proxy)服務器是網絡的中間實體。 代理位於Web客戶端和Web服務器之間,扮演“中間人”的角色。HTTP的代理服務器即是Web服務器又是Web客戶端。

代理服務器是介於客戶端和Web服務器之間的另一台服務器,有了它之後,瀏覽器不是直接到Web服務器去取回網頁而是向代理服務器發出請求,信號會先送到代理服務器,由代理服務器來取回瀏覽器所需要的信息並傳送給你的瀏覽器。

正向代理:是一個位於客戶端和原始服務器(origin server)之間的服務器,為了從原始服務器取得內容,客戶端向代理發送一個請求並指定目標(原始服務器),然後代理向原始服務器轉交請求並將獲得的內容返回給客戶端。客戶端必須要進行一些特別的設置才能使用正向代理。

反向代理服務器:在服務器端接受客戶端的請求,然後把請求分發給具體的服務器進行處理,然後再將服務器的響應結果反饋給客戶端。Nginx就是其中的一種反向代理服務器軟件。

lNginx:Nginx ("engine x") ,Nginx (“engine x”) 是俄羅斯人Igor Sysoev(塞索耶夫)編寫的一款高性能的 HTTP 和反向代理服務器。也是一個IMAP/POP3/SMTP代理服務器;也就是說,Nginx本身就可以托管網站,進行HTTP服務處理,也可以作為反向代理服務器使用。

客戶端必須設置正向代理服務器,當然前提是要知道正向代理服務器的IP地址,還有代理程序的端口。

反向代理正好與正向代理相反,對於客戶端而言代理服務器就像是原始服務器,並且客戶端不需要進行任何特別的設置。客戶端向反向代理的命名空間(name-space)中的內容發送普通請求,接著反向代理將判斷向何處(原始服務器)轉交請求,並將獲得的內容返回給客戶端。

1.1 代理服務器的好處

3.jpg

代理服務器架構

提高訪問速度 由於目標主機返回的數據會存放在代理服務器的硬盤中,因此下一次客戶再訪問相同的站點數據時,會直接從代理服務器的硬盤中讀取,起到了緩存的作用,尤其對於熱門站點能明顯提高請求速度。

防火牆作用 由於所有的客戶機請求都必須通過代理服務器訪問遠程站點,因此可在代理服務器上設限,過濾某些不安全信息。

通過代理服務器訪問不能訪問的目標站點 互聯網上有許多開發的代理服務器,客戶機在訪問受限時,可通過不受限的代理服務器訪問目標站點,通俗說,我們使用的翻牆瀏覽器就是利用了代理服務器,雖然不能出國,但也可直接訪問外網。

1.2. 代理服務器的分類

正向代理:架設在客戶機與目標主機之間,隻用於代理內部網絡對Internet的連接請求,客戶機必須指定代理服務器,並將本來要直接發送到Web服務器上的http請求發送到代理服務器中。 用戶能感知到代理服務器的存在。

反向代理:現在許多大型web網站都用到反向代理。除了可以防止外網對內網服務器的惡性攻擊、緩存以減少服務器的壓力和訪問安全控製之外,還可以進行負載均衡,將用戶請求分配給多個服務器。 用戶對代理服務器無感知。

Nginx的應用現狀

4.jpg

lNginx 已經在俄羅斯最大的門戶網站── Rambler Media(www.rambler.ru)上運行了3年時間,同時俄羅斯超過20%的虛擬主機平台采用Nginx作為反向代理服務器。在國內,已經有 淘寶、新浪博客、新浪播客、網易新聞、六間房、56.com、Discuz!、水木社區、豆瓣、YUPOO、海內、迅雷在線 等多家網站使用 Nginx 作為Web服務器或反向代理服務器。

Nginx的特點

跨平台:Nginx 可以在大多數 Unix like OS編譯運行,而且也有Windows的移植版本。

配置異常簡單,非常容易上手。配置風格跟程序開發一樣,神一般的配置

非阻塞、高並發連接:數據複製時,磁盤I/O的第一階段是非阻塞的。官方測試能夠支撐5萬並發連接,在實際生產環境中跑到2~3萬並發連接數.(這得益於Nginx使用了最新的epoll模型)

事件驅動:通信機製采用epoll模型,支持更大的並發連接。

Nginx的事件處理機製:

對於一個基本的web服務器來說,事件通常有三種類型,網絡事件、信號、定時器。

首先看一個請求的基本過程:建立連接---接收數據---發送數據 。

再次看係統底層的操作 :上述過程(建立連接---接收數據---發送數據)在係統底層就是讀寫事件。

如果采用阻塞調用的方式,當讀寫事件沒有準備好時,必然不能夠進行讀寫事件,那麼久隻好等待,等事件準備好了,才能進行讀寫事件。那麼請求就會被耽擱 。阻塞調用會進入內核等待,cpu就會讓出去給別人用了,對單線程的worker來說,顯然不合適,當網絡事件越多時,大家都在等待呢,cpu空閑下來沒人用,cpu利用率自然上不去了,更別談高並發了 。

既然沒有準備好阻塞調用不行,那麼采用非阻塞方式。非阻塞就是,事件,馬上返回EAGAIN,告訴你,事件還沒準備好呢,你慌什麼,過會再來吧。好吧,你過一會,再來檢查一下事件,直到事件準備好了為止,在這期間,你就可以先去做其它事情,然後再來看看事件好了沒。雖然不阻塞了,但你得不時地過來檢查一下事件的狀態,你可以做更多的事情了,但帶來的開銷也是不小的。

小結:非阻塞通過不斷檢查事件的狀態來判斷是否進行讀寫操作,這樣帶來的開銷很大。

因此才有了異步非阻塞的事件處理機製。具體到係統調用就是像select/poll/epoll/kqueue這樣的係統調用。他們提供了一種機製,讓你可以同時監控多個事件,調用他們是阻塞的,但可以設置超時時間,在超時時間之內,如果有事件準備好了,就返回。這種機製解決了我們上麵兩個問題。

以epoll為例:當事件沒有準備好時,就放入epoll(隊列)裏麵。如果有事件準備好了,那麼就去處理;如果事件返回的是EAGAIN,那麼繼續將其放入epoll裏麵。從而,隻要有事件準備好了,我們就去處理她,隻有當所有時間都沒有準備好時,才在epoll裏麵等著。這樣,我們就可以並發處理大量的並發了,當然,這裏的並發請求,是指未處理完的請求,線程隻有一個,所以同時能處理的請求當然隻有一個了,隻是在請求間進行不斷地切換而已,切換也是因為異步事件未準備好,而主動讓出的。這裏的切換是沒有任何代價,你可以理解為循環處理多個準備好的事件,事實上就是這樣的。

4)與多線程的比較:與多線程相比,這種事件處理方式是有很大的優勢的,不需要創建線程,每個請求占用的內存也很少,沒有上下文切換,事件處理非常的輕量級。並發數再多也不會導致無謂的資源浪費(上下文切換)。

小結:通過異步非阻塞的事件處理機製,Nginx實現由進程循環處理多個準備好的事件,從而實現高並發和輕量級。

Nginx的不為人知的特點

lnginx代理和後端web服務器間無需長連接;

接收用戶請求是異步的,即先將用戶請求全部接收下來,再一次性發送後後端web服務器,極大的減輕後端web服務器的壓力;

發送響應報文時,是邊接收來自後端web服務器的數據,邊發送給客戶端的;

網絡依賴型低。NGINX對網絡的依賴程度非常低,理論上講,隻要能夠ping通就可以實施負載均衡,而且可以有效區分內網和外網流量;

支持服務器檢測。NGINX能夠根據應用服務器處理頁麵返回的狀態碼、超時信息等檢測服務器是否出現故障,並及時返回錯誤的請求重新提交到其它節點上;

Nginx的內部(進程)模型

5.jpg

nginx是以多進程的方式來工作的,當然nginx也是支持多線程的方式的,隻是我們主流的方式還是多進程的方式,也是nginx的默認方式。nginx采用多進程的方式有諸多好處。

(1) nginx在啟動後,會有一個master進程和多個worker進程。master進程主要用來管理worker進程,包含:接收來自外界的信號,向各worker進程發送信號,監控 worker進程的運行狀態,當worker進程退出後(異常情況下),會自動重新啟動新的worker進程。而基本的網絡事件,則是放在worker進程中來處理了 。多個worker進程之間是對等的,他們同等競爭來自客戶端的請求,各進程互相之間是獨立的 。一個請求,隻可能在一個worker進程中處理,一個worker進程,不可能處理其它進程的請求。 worker進程的個數是可以設置的,一般我們會設置與機器cpu核數一致,這裏麵的原因與nginx的進程模型以及事件處理模型是分不開的 。

(2) Master接收到信號以後怎樣進行處理(./nginx -s reload )?首先master進程在接到信號後,會先重新加載配置文件,然後再啟動新的進程,並向所有老的進程發送信號,告訴他們可以光榮退休了。新的進程在啟動後,就開始接收新的請求,而老的進程在收到來自master的信號後,就不再接收新的請求,並且在當前進程中的所有未處理完的請求處理完成後,再退出 .

(3) worker進程又是如何處理請求的呢?我們前麵有提到,worker進程之間是平等的,每個進程,處理請求的機會也是一樣的。當我們提供80端口的http服務時,一個連接請求過來,每個進程都有可能處理這個連接,怎麼做到的呢?首先,每個worker進程都是從master進程fork過來,在master進程裏麵,先建立好需要listen的socket之後,然後再fork出多個worker進程,這樣每個worker進程都可以去accept這個socket(當然不是同一個socket,隻是每個進程的這個socket會監控在同一個ip地址與端口,這個在網絡協議裏麵是允許的)。一般來說,當一個連接進來後,所有在accept在這個socket上麵的進程,都會收到通知,而隻有一個進程可以accept這個連接,其它的則accept失敗,這是所謂的驚群現象。當然,nginx也不會視而不見,所以nginx提供了一個accept_mutex這個東西,從名字上,我們可以看這是一個加在accept上的一把共享鎖。有了這把鎖之後,同一時刻,就隻會有一個進程在accpet連接,這樣就不會有驚群問題了。accept_mutex是一個可控選項,我們可以顯示地關掉,默認是打開的。當一個worker進程在accept這個連接之後,就開始讀取請求,解析請求,處理請求,產生數據後,再返回給客戶端,最後才斷開連接,這樣一個完整的請求就是這樣的了。我們可以看到,一個請求,完全由worker進程來處理,而且隻在一個worker進程中處理。

(4) nginx采用這種進程模型有什麼好處呢?采用獨立的進程,可以讓互相之間不會影響,一個進程退出後,其它進程還在工作,服務不會中斷,master進程則很快重新啟動新的worker進程。當然,worker進程的異常退出,肯定是程序有bug了,異常退出,會導致當前worker上的所有請求失敗,不過不會影響到所有請求,所以降低了風險。當然,好處還有很多,大家可以慢慢體會。

(5) 有人可能要問了,nginx采用多worker的方式來處理請求,每個worker裏麵隻有一個主線程,那能夠處理的並發數很有限啊,多少個worker就能處理多少個並發,何來高並發呢?非也,這就是nginx的高明之處,nginx采用了異步非阻塞的方式來處理請求,也就是說,nginx是可以同時處理成千上萬個請求的 .對於IIS服務器每個請求會獨占一個工作線程,當並發數上到幾千時,就同時有幾千的線程在處理請求了。這對操作係統來說,是個不小的挑戰,線程帶來的內存占用非常大,線程的上下文切換帶來的cpu開銷很大,自然性能就上不去了,而這些開銷完全是沒有意義的。我們之前說過,推薦設置worker的個數為cpu的核數,在這裏就很容易理解了,更多的worker數,隻會導致進程來競爭cpu資源了,從而帶來不必要的上下文切換。而且,nginx為了更好的利用多核特性,提供了cpu親緣性的綁定選項,我們可以將某一個進程綁定在某一個核上,這樣就不會因為進程的切換帶來cache的失效。

Nginx是如何處理一個請求

首先,nginx在啟動時,會解析配置文件,得到需要監聽的端口與ip地址,然後在nginx的master進程裏麵,先初始化好這個監控的socket(創建socket,設置addrreuse等選項,綁定到指定的IP地址端口,再listen),然後再fork(一個現有進程可以調用fork函數創建一個新進程。由fork創建的新進程被稱為子進程 )出多個子進程出來,然後子進程會競爭accept新的連接。此時,客戶端就可以向nginx發起連接了。當客戶端與nginx進行三次握手,與nginx建立好一個連接後,此時,某一個子進程會accept成功,得到這個建立好的連接的socket,然後創建nginx對連接的封裝,即ngx_connection_t結構體。接著,設置讀寫事件處理函數並添加讀寫事件來與客戶端進行數據的交換。最後,nginx或客戶端來主動關掉連接,到此,一個連接就壽終正寢了,當然,nginx也是可以作為客戶端來請求其它server的數據的(如upstream模塊),此時,與其它server創建的連接,也封裝在ngx_connection_t中。作為客戶端,nginx先獲取一個ngx_connection_t結構體,然後創建socket,並設置socket的屬性( 比如非阻塞)。然後再通過添加讀寫事件,調用connect/read/write來調用連接,最後關掉連接,並釋放ngx_connection_t。

nginx在實現時,是通過一個連接池來管理的,每個worker進程都有一個獨立的連接池,連接池的大小是worker_connections。這裏的連接池裏麵保存的其實不是真實的連接,它隻是一個worker_connections大小的一個ngx_connection_t結構的數組。並且,nginx會通過一個鏈表free_connections來保存所有的空閑ngx_connection_t,每次獲取一個連接時,就從空閑連接鏈表中獲取一個,用完後,再放回空閑連接鏈表裏麵。

在這裏,很多人會誤解worker_connections這個參數的意思,認為這個值就是nginx所能建立連接的最大值。其實不然,這個值是表示每個worker進程所能建立連接的最大值,所以,一個nginx能建立的最大連接數,應該是worker_connections * worker_processes。當然,這裏說的是最大連接數,對於HTTP請求本地資源來說,能夠支持的最大並發數量是worker_connections * worker_processes,而如果是HTTP作為反向代理來說,最大並發數量應該是worker_connections * worker_processes/2。因為作為反向代理服務器,每個並發會建立與客戶端的連接和與後端服務的連接,會占用兩個連接。

Nginx典型的應用場景

6.jpg

載均衡技術在現有網絡結構之上提供了一種廉價、有效、透明的方法,來擴展網絡設備和服務器的帶寬、增加吞吐量、加強網絡數據處理能力、提高網絡的靈活性和可用性。它有兩方麵的含義:首先,大量的並發訪問或數據流量分擔到多台節點設備上分別處理,減少用戶等待響應的時間;其次,單個重負載的運算分擔到多台節點設備上做並行處理,每個節點設備處理結束後,將結果彙總,返回給用戶,係統處理能力得到大幅度提高。

來源:技術學派頭條號

华体会hth体育网 賞析
  • 2101期學員李思庭作品

    2101期學員李思庭作品

  • 2104期學員林雪茹作品

    2104期學員林雪茹作品

  • 2107期學員趙淩作品

    2107期學員趙淩作品

  • 2107期學員趙燃作品

    2107期學員趙燃作品

  • 2106期學員徐正浩作品

    2106期學員徐正浩作品

  • 2106期學員弓莉作品

    2106期學員弓莉作品

  • 2105期學員白羽新作品

    2105期學員白羽新作品

  • 2107期學員王佳蕊作品

    2107期學員王佳蕊作品

專業問題谘詢

你擔心的問題,火星幫你解答

微信掃碼入群領福利

掃碼領福利最新AI資訊

點擊谘詢
添加老師微信,馬上領取免費課程資源

1. 打開微信掃一掃,掃描左側二維碼

2. 添加老師微信,馬上領取免費課程資源

×

同學您好!

您已成功報名0元試學活動,老師會在第一時間與您取得聯係,請保持電話暢通!
確定