Nginx支援比Apache高併發的原因

破棉襖發表於2015-05-26

看到一個面試題,Nginx支援的併發為何比Apache要高?當時的第一反應就是 Apache是多程式多執行緒的的,Nginx是單執行緒的。
仔細研究後發現東西還很多:


1.先從各自使用的多路複用IO模型說起:
 
select模型:(apache使用,由於受模組等限制,用的不多)

  
  1. 單個程式能夠 監視的檔案描述符的數量存在最大限制
  2. select()所維護的 儲存大量檔案描述符的資料結構 ,隨著檔案描述符數量的增長,其在使用者態和核心的地址空間的複製所引發的開銷也會線性增長
  3. 由於網路響應時間的延遲使得大量TCP連線處於非活躍狀態,但呼叫select()還是會對 所有的socket進行一次線性掃描 ,會造成一定的開銷

poll:

poll是unix沿用select自己重新實現了一遍,唯一解決的問題是poll 沒有最大檔案描述符數量的限制

epoll模型:(nginx使用)

epoll帶來了兩個優勢,大幅度提升了效能:

  1. 基於事件的就緒通知方式 ,select/poll方式,程式只有在呼叫一定的方法後,核心才會對所有監視的檔案描述符進行掃描,而epoll事件透過epoll_ctl()註冊一個檔案描述符,一旦某個檔案描述符就緒時,核心會採用類似call back的回撥機制,迅速啟用這個檔案描述符,epoll_wait()便會得到通知
  2. 呼叫一次epoll_wait()獲得就緒檔案描述符時,返回的並不是實際的描述符,而是一個代表就緒描述符數量的值,拿到這些值去epoll指定的一個陣列中依次取得相應數量的檔案描述符即可,這裡使用記憶體對映(mmap)技術, 避免了複製大量檔案描述符帶來的開銷

當然epoll也有一定的侷限性, epoll只有Linux2.6才有實現 ,而其他平臺都沒有,這和apache這種優秀的跨平臺伺服器,顯然是有些背道而馳了。

簡單來說epoll是select的升級版,單程式管理的檔案描述符沒有最大限制。但epoll只有linux平臺可使用。作為跨平臺的Apache沒有使用。

2.再看一下Apache常用的兩種併發策略:

      1) perfork模式的工作原理:  
                    當Apache被啟動時,Apache會自動建立StartServers個程式,並且盡力將空閒程式數保持在MinSpareServers和MaxSpareServers之間。
                    如果空閒程式小於MinSpareServers,Apache將會以大約每秒1個的速度新建程式。
                    如果空閒程式小於MaxSpareServers,Apache將會刪除多餘的空閒程式,釋放伺服器資源。
                    程式數的最大值由MaxClients控制,在Apache1.3中最大隻能設定為256,但在Apache2.0中,可以透過在配置開頭增加ServerLimit專案來突破256的限制,此時必須MaxClients  ≤ ServerLimit ≤ 20000
                    MaxRequestsPerChild用來控制每個程式在處理了多少次請求之後自動銷燬,這個引數可以設定為0表示無限(即不銷燬程式)

     2) worker模式的工作原理:
            由主控制程式生成“StartServers”個子程式,每個子程式中包含固定的ThreadsPerChild執行緒數,各個執行緒獨立地處理請求。
            同樣,為了不在請求到來時再生成執行緒,MinSpareThreads和MaxSpareThreads設定了最少和最多的空閒執行緒數;而MaxClients設定允許的最大執行緒總數。
            如果現有子程式中的執行緒總數不能滿足負載,控制程式將派生新的子程式。
           每個子執行緒處理服務請求次數由MaxRequestPerChild定義。 預設的設定值為0,即響應無限此請求。
           預設生成3個子程式來處理請求。

  兩種策略的缺陷:
        perfork模式:每一個連線建立一個程式,每個程式內單執行緒。對於一個負載相對較高的網站來說,256的程式限制是不夠的,如果伺服器已經達到256的極限,那麼接下去的訪問就需要排隊,這也就是為什麼某些伺服器負載不高,但是訪問卻很慢的原因之一。

        worker模式:也是多程式處理,也會建立多個程式和多個執行緒,如果程式數達到管理員設定的閥值,則會拒絕新的請求。
       兩種模式都會建立多個程式或執行緒,而每個程式或執行緒都會為其分配cpu和記憶體(執行緒要比程式小的多,所以worker支援比perfork高的併發),併發過大會榨乾伺服器資源。


3.Nginx的工作原理:

      Nginx並不會為每一個的web請求建立新的程式,相反,管理員可以配置Nginx主程式的工作程式的數量(一個常見的做法是為每一個CPU配置一個工作程式)。所有這些程式都是單執行緒的。
      每一個工作程式可以處理數千個併發的請求。它透過一個執行緒來非同步非阻塞的完成了這些工作(epoll),而沒有使用多執行緒的程式設計模型。

 
  nginx的優勢:

      採用單執行緒來非同步非阻塞處理請求,不會為每個請求分配cpu和記憶體資源,節省了大量資源,同時也減少了大量的CPU的上下文切換。所以才使得Nginx支援更高的併發。



資料快取在程式中的方面思考?
     



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29754888/viewspace-1672476/,如需轉載,請註明出處,否則將追究法律責任。

相關文章