乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Apache與Nginx網絡模型

       牽牛吃草 2016-06-30

            Nginx的高并發(fā)得益于其采用了epoll模型,與傳統(tǒng)的服務器程序架構不同,epoll是linux內核2.6以后才出現(xiàn)的。下面通過比較Apache和Nginx工作原理來比較。

       

            傳統(tǒng)Apache都是多進程或者多線程來工作,假設是多進程工作(prefork),apache會先生成幾個進程,類似進程池的工作原理,只不過這里的進程池會隨著請求數(shù)目的增加而增加。對于每一個連接,apache都是在一個進程內處理完畢。具體是 recv(),以及根據(jù) URI 去進行磁盤I/O來尋找文件,還有 send()都是阻塞的。其實說白了都是 apche 對于套接字的I/O,讀或者寫,但是讀或者寫都是阻塞的,阻塞意味著進程就得掛起進入sleep狀態(tài),那么一旦連接數(shù)很多,Apache必然要生成更多的進程來響應請求,一旦進程多了,CPU對于進程的切換就頻繁了,很耗資源和時間,所以就導致apache性能下降了,說白了就是處理不過來這么多進程了。其實仔細想想,如果對于進程每個請求都沒有阻塞,那么效率肯定會提高很多。

       

            Nginx采用epoll模型,異步非阻塞。對于Nginx來說,把一個完整的連接請求處理都劃分成了事件,一個一個的事件。比如accept(), recv(),磁盤I/O,send()等,每部分都有相應的模塊去處理,一個完整的請求可能是由幾百個模塊去處理。真正核心的就是事件收集和分發(fā)模塊,這就是管理所有模塊的核心。只有核心模塊的調度才能讓對應的模塊占用CPU資源,從而處理請求。拿一個HTTP請求來說,首先在事件收集分發(fā)模塊注冊感興趣的監(jiān)聽事件,注冊好之后不阻塞直接返回,接下來就不需要再管了,等待有連接來了內核會通知你(epoll的輪詢會告訴進程),cpu就可以處理其他事情去了。一旦有請求來,那么對整個請求分配相應的上下文(其實已經預先分配好),這時候再注冊新的感興趣的事件(read函數(shù)),同樣客戶端數(shù)據(jù)來了內核會自動通知進程可以去讀數(shù)據(jù)了,讀了數(shù)據(jù)之后就是解析,解析完后去磁盤找資源(I/O),一旦I/O完成會通知進程,進程開始給客戶端發(fā)回數(shù)據(jù)send(),這時候也不是阻塞的,調用后就等內核發(fā)回通知發(fā)送的結果就行。整個下來把一個請求分成了很多個階段,每個階段都到很多模塊去注冊,然后處理,都是異步非阻塞。異步這里指的就是做一個事情,不需要等返回結果,做好了會自動通知你。

      select/epoll的特點

      select的特點:select 選擇句柄的時候,是遍歷所有句柄,也就是說句柄有事件響應時,select需要遍歷所有句柄才能獲取到哪些句柄有事件通知,因此效率是非常低。但是如果連接很少的情況下, select和epoll的LT觸發(fā)模式相比, 性能上差別不大。
      這里要多說一句,select支持的句柄數(shù)是有限制的, 同時只支持1024個,這個是句柄集合限制的,如果超過這個限制,很可能導致溢出,而且非常不容易發(fā)現(xiàn)問題, 當然可以通過修改linux的socket內核調整這個參數(shù)。
      epoll的特點:epoll對于句柄事件的選擇不是遍歷的,是事件響應的,就是句柄上事件來就馬上選擇出來,不需要遍歷整個句柄鏈表,因此效率非常高,內核將句柄用紅黑樹保存的。
      對于epoll而言還有ET和LT的區(qū)別,LT表示水平觸發(fā),ET表示邊緣觸發(fā),兩者在性能以及代碼實現(xiàn)上差別也是非常大的。

       Epoll模型主要負責對大量并發(fā)用戶的請求進行及時處理,完成服務器與客戶端的數(shù)據(jù)交互。其具體的實現(xiàn)步驟如下:
      (a) 使用epoll_create()函數(shù)創(chuàng)建文件描述,設定將可管理的最大socket描述符數(shù)目。
      (b) 創(chuàng)建與epoll關聯(lián)的接收線程,應用程序可以創(chuàng)建多個接收線程來處理epoll上的讀通知事件,線程的數(shù)量依賴于程序的具體需要。
      (c) 創(chuàng)建一個偵聽socket描述符ListenSock;將該描述符設定為非阻塞模式,調用Listen()函數(shù)在套接字上偵聽有無新的連接請求,在 epoll_event結構中設置要處理的事件類型EPOLLIN,工作方式為 epoll_ET,以提高工作效率,同時使用epoll_ctl()注冊事件,最后啟動網絡監(jiān)視線程。
      (d) 網絡監(jiān)視線程啟動循環(huán),epoll_wait()等待epoll事件發(fā)生。
      (e) 如果epoll事件表明有新的連接請求,則調用accept()函數(shù),將用戶socket描述符添加到epoll_data聯(lián)合體,同時設定該描述符為非 阻塞,并在epoll_event結構中設置要處理的事件類型為讀和寫,工作方式為epoll_ET.
      (f) 如果epoll事件表明socket描述符上有數(shù)據(jù)可讀,則將該socket描述符加入可讀隊列,通知接收線程讀入數(shù)據(jù),并將接收到的數(shù)據(jù)放入到接收數(shù)據(jù) 的鏈表中,經邏輯處理后,將反饋的數(shù)據(jù)包放入到發(fā)送數(shù)據(jù)鏈表中,等待由發(fā)送線程發(fā)送。

      epoll的操作就這么簡單,總共不過4個 API:epoll_create, epoll_ctl, epoll_wait和close。

            可以舉一個簡單的例子來說明Apache的工作流程,我們平時去餐廳吃飯。餐廳的工作模式是一個服務員全程服務客戶,流程是這樣,服務員在門口等候客人(listen),客人到了就接待安排的餐桌上(accept),等著客戶點菜(request uri),去廚房叫師傅下單做菜(磁盤I/O),等待廚房做好(read),然后給客人上菜(send),整個下來服務員(進程)很多地方是阻塞的。這樣客人一多(HTTP請求一多),餐廳只能通過叫更多的服務員來服務(fork進程),但是由于餐廳資源是有限的(CPU),一旦服務員太多管理成本很高(CPU上下文切換),這樣就進入一個瓶頸。
      再來看看Nginx得怎么處理?餐廳門口掛個門鈴(注冊epoll模型的listen),一旦有客人(HTTP請求)到達,派一個服務員去接待(accept),之后服務員就去忙其他事情了(比如再去接待客人),等這位客人點好餐就叫服務員(數(shù)據(jù)到了read()),服務員過來拿走菜單到廚房(磁盤I/O),服務員又做其他事情去了,等廚房做好了菜也喊服務員(磁盤I/O結束),服務員再給客人上菜(send()),廚房做好一個菜就給客人上一個,中間服務員可以去干其他事情。整個過程被切分成很多個階段,每個階段都有相應的服務模塊。我們想想,這樣一旦客人多了,餐廳也能招待更多的人。

              不管是Nginx還是Squid這種反向代理,其網絡模式都是事件驅動。事件驅動其實是很老的技術,早期的select、poll都是如此。后來基于內核通知的更高級事件機制出現(xiàn),如libevent里的epoll,使事件驅動性能得以提高。事件驅動的本質還是IO事件,應用程序在多個IO句柄間快速切換,實現(xiàn)所謂的異步IO。事件驅動服務器,最適合做的就是這種IO密集型工作,如反向代理,它在客戶端與WEB服務器之間起一個數(shù)據(jù)中轉作用,純粹是IO操作,自身并不涉及到復雜計算。反向代理用事件驅動來做,顯然更好,一個工作進程就可以run了,沒有進程、線程管理的開銷,CPU、內存消耗都小。

        所以Nginx、Squid都是這樣做的。當然,Nginx也可以是多進程 + 事件驅動的模式,幾個進程跑libevent,不需要Apache那樣動輒數(shù)百的進程數(shù)。Nginx處理靜態(tài)文件效果也很好,那是因為靜態(tài)文件本身也是磁盤IO操作,處理過程一樣。至于說多少萬的并發(fā)連接,這個毫無意義。隨手寫個網絡程序都能處理幾萬的并發(fā),但如果大部分客戶端阻塞在那里,就沒什么價值。

        再看看Apache或者Resin這類應用服務器,之所以稱他們?yōu)閼梅掌?,是因為他們真的要跑具體的業(yè)務應用,如科學計算、圖形圖像、數(shù)據(jù)庫讀寫等。它們很可能是CPU密集型的服務,事件驅動并不合適。例如一個計算耗時2秒,那么這2秒就是完全阻塞的,什么event都沒用。想想MySQL如果改成事件驅動會怎么樣,一個大型的join或sort就會阻塞住所有客戶端。這個時候多進程或線程就體現(xiàn)出優(yōu)勢,每個進程各干各的事,互不阻塞和干擾。當然,現(xiàn)代CPU越來越快,單個計算阻塞的時間可能很小,但只要有阻塞,事件編程就毫無優(yōu)勢。所以進程、線程這類技術,并不會消失,而是與事件機制相輔相成,長期存在。

        總言之,事件驅動適合于IO密集型服務,多進程或線程適合于CPU密集型服務,它們各有各的優(yōu)勢,并不存在誰取代誰的傾向。

       

        本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多