web服務器主要任務就是處理來自客戶端的請求,通常狀況下Web服務器處理併發鏈接請求的工做模型有如下幾種方式:php
一、單線程web服務器(Single-threaded web servers)
此種架構方式中,web服務器一次處理一個請求,結束後讀取並處理下一個請求。在某請求處理過程當中,其它全部的請求將被忽略,所以,在併發請求較多的場景中將會出現嚴重的性能問題。(即一次只能處理一個請求)mysql
二、多進程/多線程web服務器
此種架構方式中,web服務器生成多個進程或線程並行處理多個用戶請求,進程或線程能夠按需或事先生成。有的web服務器應用程序爲每一個用戶請求生成一個單獨的進程或線程來進行響應,不過,一旦併發請求數量達到成千上萬時,多個同時運行的進程或線程將會消耗大量的系統資源。(即每一個進程只能響應一個請求,而且一個進程對應一個線程)linux
三、I/O多路複用web服務器
爲了可以支持更多的併發用戶請求,愈來愈多的web服務器正在採用多種複用的架構———即同步監控全部的鏈接請求的活動狀態,當一個鏈接的狀態發生改變時(如數據準備完畢或發生某錯誤),將爲其執行一系列特定操做;在操做完成後,此鏈接將從新變回暫時的穩定態並返回至打開的鏈接列表中,直到下一次的狀態改變。因爲其多路複用的特性,進程或線程不會被空閒的鏈接所佔用,於是能夠提供高效的工做模式。(這種架構能夠理解爲一個進程能夠生成多個線程,每一個請求交給一個線程進行處理)nginx
四、多路複用多線程web服務器
將多進程和多路複用的功能結合起來造成的web服務器架構,其避免了讓一個進程服務於過多的用戶請求,並能充分利用多CPU主機所提供的計算能力。(這種架構能夠理解爲有多個進程,而且一個進程又生成多個線程,每一個線程處理一個請求)web
linux下經常使用的I/O模型(這裏借用下在網上查閱的資料,感受還好理解):
先引入select和epoll概念:
select和epoll是兩個處理I/O模型的機制,能夠加速請求處理,2者處理方式不一樣:通俗的講,select機制是對沒有處理好的I/O請求在一段時間內進行檢測,並將其狀態通知給用戶,即有沒有完成都會通知。而epool機制則是在該I/O請求完成後才通知給用戶。sql
在Unix/Linux下共有五種I/O模型,分別是:
1)阻塞I/O
2)非阻塞I/O
3)I/O複用(select和poll)
4)信號驅動I/O(SIGIO)
5)異步I/O(Posix.1的aio_系列函數)數據庫
對以上模型的比較:
阻塞I/O:
應用程序調用一個IO函數,致使應用程序阻塞,等待數據準備好。 若是數據沒有準備好,一直等待….數據準備好了,從內核拷貝到用戶空間,IO函數返回成功指示apache
非阻塞I/O:
咱們把一個套接口設置爲非阻塞就是告訴內核,當所請求的I/O操做沒法完成時,不要將進程睡眠,而是返回一個錯誤。這樣咱們的I/O操做函數將不斷的測試數據是否已經準備好,若是沒有準備好,繼續測試,直到數據準備好爲止。在這個不斷測試的過程當中,會大量的佔用CPU的時間。瀏覽器
I/O複用(select和poll):
I/O複用模型會用到select或者poll函數,這兩個函數也會使進程阻塞,可是和阻塞I/O所不一樣的的,這兩個函數能夠同時阻塞多個I/O操做。並且能夠同時對多個讀操做,多個寫操做的I/O函數進行檢測,直到有數據可讀或可寫時,才真正調用I/O操做函數。緩存
信號驅動I/O(SIGIO):
首先咱們容許套接口進行信號驅動I/O,並安裝一個信號處理函數,進程繼續運行並不阻塞。當數據準備好時,進程會收到一個SIGIO信號,能夠在信號處理函數中調用I/O操做函數處理數據。
異步I/O(Posix.1的aio_系列函數):
當一個異步過程調用發出後,調用者不能馬上獲得結果。實際處理這個調用的部件在完成後,經過狀態、通知和回調來通知調用者的輸入輸出操做
回顧下apache的工做模塊:
prefork:多進程,每一個請求用一個進程響應,這個過程會用到select機制來通知。
worker:多進程,一個進程能夠生成多個線程,每一個線程響應一個請求。
event:一個進程,每一個進程響應多個用戶請求,它是基於事件實現的。
基於事件機制的特性:
一個進程響應多個用戶請求,利用run-loop機制,讓套接字複用,請求過來後進程並不處理請求,而是直接交由其餘機制來處理,經過select或epoll機制來通知請求是否完成;在這個過程當中,進程自己一直處於空閒狀態,能夠一直接收用戶請求。
對於高併發請求的實現:
一、基於線程:即一個進程生成多個線程,每一個線程響應用戶的每一個請求。如worker模型
二、基於事件的模型,一個進程處理多個請求,而且經過epoll機制來通知用戶請求完成。如event模型
web服務器工做流程:
咱們知道web服務器是工做在用戶空間的,用戶空間經過系統調用來與內核打交道。
用戶請求-->送達用戶空間-->系統調用-->內核空間-->內核到磁盤上讀取網頁資源(在此過程當中就牽涉到了以上幾種模型的運用)
傳統上基於進程或線程模型架構的web服務經過每進程或每線程處理併發鏈接請求,這勢必會在網絡和I/O操做時產生阻塞,其另外一個必然結果則是對內存或CPU的利用率低下。生成一個新的進程/線程須要事先備好其運行時環境,這包括爲其分配堆內存和棧內存,以及爲其建立新的執行上下文等。這些操做都須要佔用CPU,並且過多的進程/線程還會帶來線程抖動或頻繁的上下文切換,系統性能也會由此進一步降低。
另外一種高性能web服務器/web服務器反向代理:Nginx同(Engine X)
nginx的主要着眼點就是其高性能以及對物理計算資源的高密度利用,所以其採用了不一樣的架構模型。受啓發於多種操做系統設計中基於「事件」的高級處理機制,nginx採用了模塊化、事件驅動、異步、單線程及非阻塞的架構,並大量採用了多路複用及事件通知機制。在nginx中,鏈接請求由爲數很少的幾個僅包含一個線程的進程worker以高效的迴環(run-loop)機制進行處理,而每一個worker能夠並行處理數千個的併發鏈接及請求。
Nginx會按需同時運行多個進程:一個主進程(master)和幾個工做進程(worker),配置了緩存時還會有緩存加載器進程(cache loader)和緩存管理器進程(cache manager)等。全部進程均是僅含有一個線程,並主要經過「共享內存」的機制實現進程間通訊。主進程以root用戶身份運行,而worker、cache loader和cache manager均應以非特權用戶身份運行。
主進程主要完成以下工做:
worker進程主要完成的任務包括:
Nginx的代碼是由一個核心和一系列的模塊組成, 核心主要用於提供Web Server的基本功能,以及Web和Mail反向代理的功能;還用於啓用網絡協議,建立必要的運行時環境以及確保不一樣的模塊之間平滑地進行交互。不過,大多跟協議相關的功能和某應用特有的功能都是由nginx的模塊實現的。這些功能模塊大體能夠分爲事件模塊、階段性處理器、輸出過濾器、變量處理器、協議、upstream和負載均衡幾個類別,這些共同組成了nginx的http功能。事件模塊主要用於提供OS獨立的(不一樣操做系統的事件機制有所不一樣)事件通知機制如kqueue或epoll等。協議模塊則負責實現nginx經過http、tls/ssl、smtp、pop3以及imap與對應的客戶端創建會話。
在nginx內部,進程間的通訊是經過模塊的pipeline或chain實現的;換句話說,每個功能或操做都由一個模塊來實現。例如,壓縮、經過FastCGI或uwsgi協議與upstream服務器通訊,以及與memcached創建會話等。
緩存機制:
咱們知道,用戶請求不止要請求靜態內容,反而大多數請求的都是動態類的網頁,在請求動態內容時,php服務器要和mysql打交道,若是請求數量太多,這勢必會致使響應用戶請求的速度變慢,爲了解決這一問題,咱們還要引入緩存的概念。
在這裏咱們引入一個加速緩存的工具:Memcached
Memcached是一款開源、高性能、分佈式內存對象緩存系統,可應用各類須要緩存的場景,其主要目的是經過下降對Database的訪問來加速web應用程序。它是一個基於內存的「鍵值對」存儲,用於存儲數據庫調用、API調用或頁面引用結果的直接數據,如字符串、對象等。
Memcached是一款開發工具,它既不是一個代碼加速器,也不是數據庫中間件。其設計哲學思想主要反映在以下方面:
Memcached提供了爲數很少的幾個命令來完成與服務器端的交互,這些命令基於memcached的協議實現。
存儲類命令:set, add, replace, append, prepend
獲取數據類命令:get, delete, incr/decr
統計類命令:stats, stats items, stats slabs, stats sizes
清理命令: flush_all
下一篇內容會介紹到nginx和memcache的配置哦^_^
補充:代理的概念
Web代理服務器工做於web客戶端和web服務器之間,它負責接收來自於客戶端的http請求,並將其轉發至對應的服務;然後接收來自於服務端的響應,並將響應報文回送至客戶端。
客戶端連上web服務器後,若想得到web服務器中的某個web資源,需遵照必定的通信格式,HTTP協議用於定義客戶端與web服務器通迅的格式。WEB瀏覽器與WEB服務器之間的一問一答的交互過程必須遵循必定的規則,這個規則就是HTTP協議