關於 CGI 和 FastCGI 的理解

1. CGI的引入

在網站的整體架構中, Web Server (如 nginx, apache) 只是內容的分發者, 對客戶端的請求進行應答.

若客戶端請求的是 index.html 這類靜態頁面, 那麼 Web Server 就去文件系統中找對應的文件, 找到返回給客戶端 (一般是瀏覽器), 在這裏 Web Server 分發的就是是靜態數據.

在這裏插入圖片描述

若客戶端請求的是 index.php 這類的動態頁面請求, Web Server 根據配置文件知道這個不是靜態文件, 則會調用 PHP 解析器 進行處理然後將返回的數據轉發給客戶端 (一般是瀏覽器), 在這裏 Web Server 分發的就是是動態數據.

在這裏插入圖片描述

在這個過程中, Web Server 並不能直接處理靜態或者動態請求, 對於靜態請求是直接查找然後返回數據或者報錯信息, 對於動態數據也是交付給其他的工具 (例如: PHP 解析器) 進行處理.

那麼 Web Server 和處理工具 (例如: php-fpm) 是怎樣進行交互的呢? 傳輸的是那些數據呢? 這些數據的格式又是怎樣的呢?

由此便引出了今天的主角: CGI.

2. 關於 CGI

2.1 CGI 的概念

  1. CGI (Common Gateway Interface) 全稱是 “通用網關接口”, 是一種讓客戶端 (web瀏覽器) 與Web服務器 (nginx等)程序進行通信 (數據傳輸)的協議. 用來規範 web 服務器傳輸到 PHP 解釋器中的數據類型以及數據格式,
    包括URL, 查詢字符串、POST 數據, HTTP header 等, 也就是爲了保證 web server 傳遞過來的數據是標準格式的.
  2. CGI 可以用任何一種具有標準輸入, 輸出和環境變量的語言編寫, 如 PHP, PERL、TCL 等. 不同類型語言寫的程序只要符合 CGI 標準, 就能作爲一個 CGI 程序與 web 服務器交互, 早期的 CGI 大多都是 C 或 C++ 編寫的.
  3. 一般說的 CGI 指的是用各種語言編寫的能實現該功能的程序.

2.2 CGI 程序的工作原理

  1. 每次當 web server 收到 index.php 這種類型的動態請求後, 會啓動對應的 CGI 程序 (PHP 的解析器).
  2. PHP 解析器會解析 php.ini 配置文件, 初始化運行環境, 然後處理請求, 處理完成後將數據按照 CGI 規定的格式返回給 web server 然後退出進程.
  3. 最後 web server 再把結果返回給瀏覽器.

2.3 CGI 程序的特點

  1. 高併發時的性能較差:
    CGI 程序的每一次 web 請求都會有啓動和退出過程, 也就是最爲人詬病的 fork-and-execute 模式 (每次HTTP服務器遇到動態請求時都需要重新啓動腳本解析器來解析 php.ini, 重新載入全部 DLL 擴展並重初始化全部數據結構,
    然後把結果返回給 HTTP 服務器), 很明顯, 這樣的接口方式會導致 PHP 的性能很差, 在處理高併發訪問時, 幾乎是不可用的.
  2. 傳統的 CGI 接口方式安全性較差.
  3. CGI 對 php.ini 的配置很敏感, 在開發和調試的時候相當方便.

2.4 CGI 程序的應用領域

  1. 因爲 CGI 爲每一次請求增加一個進程, 效率很低, 所以基本已經不在生產部署時採用. 但由於 CGI 對 PHP 配置的敏感性. 通常被用在開發和調試階段.

3. 關於 FastCGI

3.1 FastCGI 的概念

通過 CGI 程序的工作原理可以看出: CGI 程序性能較差, 安全性較低, 爲了解決這些問題產生了 FastCGI.

1. FastCGI (Fast Common Gateway Interface) 全稱是 "快速通用網關接口".
     是通用網關接口 (CGI) 的增強版本, 由 CGI 發展改進而來, 主要用來提高CGI程序性能, 類似於CGI,FastCGI 也是一種讓交互程序與Web服務器通信的協議.
2. FastCGI 致力於減少網頁服務器與 CGI 程序之間互動的開銷, 從而使服務器可以同時處理更多的網頁請求 (提高併發訪問).
3. 同樣的, 一般說的FastCGI指的也是用各種語言編寫的能實現該功能的程序.

3.2 FastCGI 程序的工作原理

  1. Web Server 啓動同時, 加載 FastCGI 進程管理器 ( Nginx 的 php-fpm 或者 IIS 的 ISAPI 或 Apache 的 Module).
  2. FastCGI 進程管理器讀取 php.ini 配置文件, 對自身進行初始化, 啓動多個CGI解釋器進程 (php-cgi), 等待來自 Web Server 的連接.
  3. 當 Web Server 接收到客戶端請求時, FastCGI 進程管理器選擇並連接到一個 CGI 解釋器. Web server 會將相關環境變量和標準輸入發送到 FastCGI 子進程 php-cgi 進行處理.
  4. FastCGI 子進程完成處理後將數據按照 CGI 規定的格式返回給 Web Server, 然後關 FastCGI 子進程或者等待下一次請求.

3.3 FastCGI 對進程的管理方式

FastCGI 會先啓一個 master, 解析配置文件, 初始化執行環境, 然後再啓動多個 worker. 當請求過來時, master 會傳遞給一個 worker, 然後立即可以接受下一個請求. 這樣就避免了重複的勞動, 效率自然提高. 而且當 worker 不夠用時, master 可以根據配置預先啓動幾個 worker 等着;當然空閒 worker 太多時, 也會停掉一些, 這樣就提高了性能, 也節約了資源. 這就是 FastCGI 的對進程的管理.

3.4 FastCGI 的特點

  1. FastCGI 具有語言無關性, 支持用大多數語言進行編寫, 對應的程序也支持大多數主流的 web 服務器.
    FastCGI 技術目前支持語言有: C/C++, Java, PHP, Perl, Tcl, Python, SmallTalk, Ruby 等.
    支持 FastCGI 技術的主流 web 服務器有: Apache, Nginx, lighttpd 等.
  2. FastCGI 程序的接口方式採用 C/S 結構, 可以將 web 服務器和腳本解析服務器分開, 獨立於 web 服務器運行, 提高 web 服務器的併發性能和安全性.
    提高性能: 這種方式支持多個 web 分發服務器和多個腳本解析服務器的分佈式架構, 同時可以在腳本解析服務器上啓動一個或者多個腳本解析守護進程來處理動態請求, 可以讓 web
    服務器專一地處理靜態請求或者將動態腳本服務器的結果返回給客戶端, 這在很大程度上提高了整個應用系統的性能.
    提高安全性: API方式把應用程序的代碼與核心的 web 服務器鏈接在一起, 這時一個錯誤的 API 的應用程序可能會損壞其他應用程序或核心服務器, 惡意的API的應用程序代碼甚至可以竊取另一個應用程序或核心服務器的密鑰,
    採用這種方式可以在很大程度上避免這個問題.
  3. FastCGI 的不依賴於任何 Web 服務器的內部架構, 因此即使服務器技術的變化, FastCGI 依然穩定不變.
  4. FastCGI 程序在修改 php.ini 配置時可以進行平滑重啓加載新配置. 所有的配置加載都只在FastCGI進程啓動時發生一次, 每次修改 php.ini 配置文件, 只需要重啓 FastCGI 程序
    (php-fpm 等) 即可完成平滑加載新配置, 已有的動態請求會繼續處理, 處理完成關閉進程, 新來的請求使用新加載的配置和變量進行處理.
  5. FAST-CGI 是較新的標準, 架構上和 CGI 大爲不同, 是用一個駐留內存的服務進程向網站服務器提供腳本服務. 像是一個常駐 (long-live) 型的 CGI, 維護的是一個進程池, 它可以一直執行着, 只要激活後, 不會每次都要花費時間去 fork 一次
    (這是 CGI 最爲人詬病的 fork-and-execute 模式), 速度和效率比 CGI 大爲提高, 是目前的主流部署方式.
  6. FastCGI 的不足: 因爲是在內存中同時運行多進程, 所以會比 CGI 方式消耗更多的服務器內存, 每個 PHP-CGI 進程消耗 7 至 25 兆內存, 在進行優化配置 php-cgi 進程池的數量時要注意系統內存, 防止過量.

3.5 FastCGI 的特點 FastCGI 程序的應用領域

生產環境的主流部署方式.

4. 關於 CGI 和 FastCGI 的總結

  1. CGI 和 FastCGI 都只是一種通信協議規範, 不是一個實體, 一般說的CGI指的是用各種語言編寫的能實現該功能的程序
  2. CGI 程序和 FastCGI 程序, 是指實現這兩個協議的程序, 可以是任何語言實現這個協議的.(PHP-CGI 和 PHP-FPM就是實現FastCGI的程序)
  3. CGI 程序和 FastCGI 程序的區別:
    關於 CGI 程序:
            CGI 使外部程序與 Web 服務器之間交互成爲可能. CGI 程序運行在獨立的進程中, 並對每個Web 請求建立一個進程, 這種方法非常容易實現, 但效率很差, 難以擴展. 面對大量請求, 進程的大量建立和消亡使操作系統性能大大下降. 此外, 由於地址空間無法共享, 也限制了資源用.
    關於 FastCGI程序:
            與 CGI 程序爲每個請求創建一個新的進程不同, FastCGI 使用持續的進程 (master) 來處理一連串的請求. 這些進程由 FastCGI 服務器管理, 而不是 web 服務器. 當進來一個請求時, web 服務器把環境變量和這個頁面請求通過一個 socket 或者一個 TCP connection 傳遞給 FastCGI 進程.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章