首頁  >  文章  >  後端開發  >  nginx基礎概念-connection

nginx基礎概念-connection

WBOY
WBOY原創
2016-08-08 09:27:41846瀏覽
在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基礎概念-connection,包括了方面的內容,希望對PHP教程有興趣的朋友有幫助。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
上一篇:php優化技巧下一篇:php優化技巧