nginx中connection概念

來源:互聯網
上載者:User
在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作為反向 Proxy來說,最大並發數量應該是worker_connections * worker_processes/2。因為作為反向 Proxy伺服器,每個並發會建立與用戶端的串連和與後端服務的串連,會佔用兩個串連。

那麼,我們前面有說過一個用戶端串連過來後,多個閒置進程,會競爭這個串連,很容易看到,這種競爭會導致不公平,如果某個進程得到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教程有興趣的朋友有所協助。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.