首頁 > 後端開發 > php教程 > nginx中connection概念

nginx中connection概念

WBOY
發布: 2016-08-08 09:21:02
原創
1089 人瀏覽過
在nginx中connection就是tcp連接的封裝,其中包括連接的socket,讀取事件,寫事件。利用nginx封裝的connection,我們可以很方便的使用nginx來處理與連接相關的事情,例如,建立連接,發送與接受數據等。而nginx中的http請求的處理就是建立在connection之上的,所以nginx不僅可以作為一個web伺服器,也可以作為郵件伺服器。當然,利用nginx提供的connection,我們可以與任何後端服務打交道。 結合一個tcp連結的生命週期,我們來看看nginx是如何處理一個連結的。首先,nginx在啟動時,會解析設定文件,得到需要監聽的連接埠與ip位址,然後在nginx的master進程裡面,先初始化好這個監控的socket(創建socket,設定addrreuse等選項,綁定到指定的ip位址端口,再listen),然後再fork出多個子進程出來,然後子進程會競爭accept新的連接。此時,客戶端就可以向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中,每個進程會有一個連線數的最大上限,這個上限與系統對fd的限制不一樣。在作業系統中,透過ulimit -n,我們可以得到一個行程所能夠開啟的fd的最大數,也就是nofile,因為每個socket連線會佔用掉一個fd,所以這也會限制我們行程的最大連線數,當然也會直接影響我們程式所能支援的最大並發數,當fd用完後,再創建socket時,就會失敗。 nginx透過設定worker_connectons來設定每個進程支援的最大連線數。如果該值大於nofile,那麼實際的最大連線數是nofile,nginx會有警告。 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。因為作為反向代理伺服器,每個並發會建立與客戶端的連接和與後端服務的連接,會佔用兩個連接。 那麼,我們前面有說過一個客戶端連接過來後,多個空閒的進程,會競爭這個連接,很容易看到,這種競爭會導致不公平,如果某個進程得到accept的機會比較多,它的空閒連接很快就用完了,如果不提前做一些控制,當accept到一個新的tcp連接後,因為無法得到空閒連接,而且無法將此連接轉交給其它進程,最終會導致此tcp連接得不到處理,就中止掉了。很顯然,這是不公平的,有的進程有剩餘連接,卻沒有處理機會,有的進程因為沒有空餘連接,卻人為地丟棄連接。那麼,如何解決這個問題呢?首先,nginx的處理得先打開accept_mutex選項,此時,只有獲得了accept_mutex的進程才會去添加accept事件,也就是說,nginx會控制進程是否添加accept事件。 nginx使用一個叫ngx_accept_disabled的變數來控制是否去競爭accept_mutex鎖。在第一段程式碼中,計算ngx_accept_disabled的值,這個值是nginx單一進程的所有連接總數的八分之一,減去剩下的空閒連接數量,得到的這個ngx_accept_disabled有一個規律,當剩餘連接數小於總連接數的八分之一時,其值才大於0,而且剩餘的連接數越小,這個值越大。再看第二段程式碼,當ngx_accept_disabled大於0時,不會去嘗試取得accept_mutex鎖,並且將ngx_accept_disabled減1,於是,每次執行到此處時,都會去減1,直到小於0。不去取得accept_mutex鎖,就是等於讓出獲取連接的機會,很顯然可以看出,當空餘連接越少時,ngx_accept_disable越大,於是讓出的機會就越多,這樣其它進程獲取鎖的機會也就越大。不去accept,自己的連接就控制下來了,其它進程的連接池就會被利用,這樣,nginx就控制了多進程間連接的平衡了。 ngx_accept_disabled = ngx_cycle->connection_n / 8 - ngx_cycle->free_connection_n; if (ngx_accept_disabled > 0) { ngx_accept_disabled--; } else { if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) { return; } if (ngx_accept_mutex_held) { flags |= NGX_POST_EVENTS; } else { if (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay) { timer = ngx_accept_mutex_delay; } } }好了,連接就先介紹到這,本章的目的是介紹基本概念,知道在nginx中連接是個什麼東西就行了,而且連接是屬於比較高級的用法,在後面的模組開發高級篇會有專門的章節來講解連結與事件的實現及使用。

以上就介紹了nginx中connection概念,包含了方面的內容,希望對PHP教程有興趣的朋友有幫助。

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板