天天看點

說說http/webserver/fastcgi/php-fpm

來源:說說http/webserver/fastcgi/php-fpm

前一段時間又重讀了《HTTP權威指南》一書,覺得有一些理論知識還是蠻重要的,需要進行一番整理,讓自己之後對整條web鍊路有個更清晰的認識。

一:Http請求:

當使用者打開浏覽器并輸入一串url位址時,到最終頁面内容呈現在使用者眼前時,這之間的步驟可大緻整理如下:

1)使用者輸入http://www.lxlxw.me。

2)浏覽器解析出主機名。

3)浏覽器查詢這個主機名的ip位址如192.168.0.1(即dns解析)并獲得端口号如80

4)浏覽器發起到192.168.0.1:80的連接配接。(tcp連接配接首次握手)

5)浏覽器向伺服器發送一條http get或post封包。(有可能會先發送給proxy或gateway,再由它們轉發給伺服器,如nginx做反向代理以實作負載均衡)

6)浏覽器從伺服器讀取http響應封包。

7)浏覽器關閉連接配接。

以上便是一條http請求的大緻過程,理論上所有的http通信都是由tcp/ip承載的,即http使用tcp連接配接,其保證了在資源傳輸過程中是可靠的/不會丢失或損壞的。

注:http和https比較,https就是在http層和tcp層之間接入了一個密碼加密層,稱之為TLS或SSL,常用于一些支付等安全性要求較高的網站。

注:關于http的性能優化,tcp連接配接的時延和瓶頸等,之後可能需要另整理一份。

二:web伺服器

web伺服器可以用來表示web伺服器的軟體,也可以表示提供web頁面的特定裝置或機器。這邊主要是指通用軟體web伺服器,如apache或nginx。

《http權威指南》中有一份用perl腳本寫的web伺服器的源碼,實作了最簡單的收發用戶端封包的功能。

當然,實際的web伺服器比這要複雜的多,核心步驟整理如下:

1)接受一個用戶端(浏覽器)連接配接,或者拒絕該用戶端的連接配接并将其關閉。

2)接受請求,從網絡中讀取一條http請求封包并解析。

3)處理請求,對請求封包進行解析。

4)通路資源,通路封包中指定的資源,有可能是緩存好的html靜态頁面或圖檔資源,也有可能是動态資源,如php檔案,此時web server會通過fastcgi請求php應用程式以此産生動态資源,下面會詳細講。

5)建立http響應封包,并回送給用戶端。

6)紀錄事務處理過程,即記log。

三:Fastcgi與php-fpm:

講Fastcgi之前需要先講CGI,CGI是為了保證web server傳遞過來的資料是标準格式的,它是一個協定,友善CGI程式的編寫者。Fastcgi是CGI的更進階的一種方式,是用來提高CGI程式性能的。

web server(如nginx)隻是内容的分發者。比如,如果請求/index.html,那麼web server會去檔案系統中找到這個檔案,發送給浏覽器,這裡分發的是靜态資源。

如果現在請求的是/index.php,根據配置檔案,nginx知道這個不是靜态檔案,需要去找PHP解析器來處理,那麼他會把這個請求簡單處理後交給PHP解析器。此時CGI便是規定了要傳什麼資料/以什麼格式傳輸給php解析器的協定。

當web server收到/index.php這個請求後,會啟動對應的CGI程式,這裡就是PHP的解析器。接下來PHP解析器會解析php.ini檔案,初始化執行環境,然後處理請求,再以CGI規定的格式傳回處理後的結果,退出程序。web server再把結果傳回給浏覽器。

那麼CGI相較于Fastcgi而言其性能瓶頸在哪呢?CGI針對每個http請求都是fork一個新程序來進行處理,處理過程包括解析php.ini檔案,初始化執行環境等,然後這個程序會把處理完的資料傳回給web伺服器,最後web伺服器把内容發送給使用者,剛才fork的程序也随之退出。 如果下次使用者還請求動态資源,那麼web伺服器又再次fork一個新程序,周而複始的進行。

而Fastcgi則會先fork一個master,解析配置檔案,初始化執行環境,然後再fork多個worker。當請求過來時,master會傳遞給一個worker,然後立即可以接受下一個請求。這樣就避免了重複的勞動,效率自然是高。而且當worker不夠用時,master可以根據配置預先啟動幾個worker等着;當然空閑worker太多時,也會停掉一些,這樣就提高了性能,也節約了資源。這就是Fastcgi的對程序的管理。大多數Fastcgi實作都會維護一個程序池。注:swoole作為httpserver,實際上也是類似這樣的工作方式。

那PHP-FPM又是什麼呢?它是一個實作了Fastcgi協定的程式,用來管理Fastcgi起的程序的,即能夠排程php-cgi程序的程式。現已在PHP核心中就內建了PHP-FPM,使用–enalbe-fpm這個編譯參數即可。另外,修改了php.ini配置檔案後,沒辦法平滑重新開機,需要重新開機php-fpm才可。此時新fork的worker會用新的配置,已經存在的worker繼續處理完手上的活。

繼續閱讀