CGI FastCGI Nginx

CGI

什麼是CGI

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

CGI程序的工作原理

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

CGI程序的特點

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

CGI程序的應用領域

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

FastCGI

什麼是FastCGI

  • 通過cgi程序的工作原理可以看出:CGI程序性能較差,安全性較低,爲了解決這些問題產生了fastcgi
  • fastcgi(快速通用網管接口),主要用來提高cgi程序性能,也是一種讓交互程序與web服務器通信的協議
  • fastcgi致力於減少網頁服務器與cgi程序之間互動的開銷,從而使得服務器可以同時處理更多的網頁請求(提高併發訪問)
  • 同樣的,一般說的fastcgi指的也是各種語言編寫的能實現該功能的程序

FastCGI程序的工作原理

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

FastCGI對進程的管理方式

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

FastCGI的特點

  • Fastcgi程序的接口方式採用cs結構,,可以將web服務器和腳本解析服務器分開,獨立於web服務器運行,提高web服務器的併發性能和安全性。
    • 提高性能:這種方式支持多個web分發服務器和多個腳本解析服務器的分佈式架構,同時可以在腳本解析服務器上啓動一個或者多個腳本解析守護進程來動態處理請求,可以讓web服務器專一的處理靜態請求或者將動態腳本服務器的結果返回給客戶端,這在很大程度上提高了整個應用系統的性能。
    • 提高安全性:API方式把應用程序的代碼與核心的web服務器連接在一起,這時一個錯誤的api應用程序可能會損壞其他應用程序或核心服務器,惡意的api應用程序代碼甚至可以竊取另一個應用程序或核心服務器的密鑰,採用這種方式可以在很大程度上避免這個問題
    • fastcgi的不依賴於任何web服務器的內部架構,因此即使服務器技術的變化,fastcgi依然穩定不變
    • fastcgi程序在修改php.ini配置時可以進行平滑重啓加載新配置
      • 所有的配置加載都只在fastcgi進程啓動時發生一次,每次修改php.ini配置文件,只需要重啓fastcgi程序(php-fpm等)即可完成平滑加載新配置,已有的動態請求會繼續處理,處理完成關閉進程,新來的請求使用新加載的配置和變量進行處理
    • fastcgi是較新的標準,架構上和cgi大爲不同,是用一個駐留內存的服務進程向網站服務器提供腳本服務。像是一個常駐型的cgi,維護的是一個進程池,它可以一直執行着,只要激活後,不會每次花時間都要去fork一次
    • 不足:因爲是在內存中同時運行多進程,所以會比cgi方式消耗更多的服務器內存,每個php-cgi進程消耗7-25兆內存,在進行優化配置php-cgi進程池的數量時要注意系統內存,防止過量

關於cgi和fastcgi的總結

  • cgi和fastcgi都只是一種通信協議規範,不是一個實體,一般說的cgi指的是用各種語言編寫的能實現該功能的程序
  • cgi程序和fastcgi程序是指實現這兩個協議的程序,可以是任何語言實現這個協議的(php-cgi和php-fpm就是實現fastcgi的程序)
  • cgi程序和fastcgi程序的區別
    • 關於cgi程序
      • cgi使外部程序與web服務器之間交互成爲可能。cgi程序運行在獨立的進程中,並對每個web請求建立一個進程,這種方法非常容易實現,但效率很差,難以擴展,面對大量請求,進程的大量建立和消亡使得操作系統性能大大下降。此外,由於地址空間無法共享,也限制了資源重用。
    • 關於fastcgi程序
      • 與cgi程序爲每個請求創建一個新的進程不同,fastcgi使用持續的進程(master)來處理一連串的請求。這些進程由fastcgi服務器管理,而不是web服務器。當進來一個請求時,web服務器把環境變量和這個頁面請求通過一個socket或者tcp connection傳遞給fastcgi進程。
      • fast-cgi每次處理完請求後,不會kill掉這個進程,而是保留這個進程,使這個進程可以一次處理多個請求。這樣每次就不用重新fork一個進程了,大大提高了效率。

php-cgi php-fpm spawn-fcgi

php-cgi是什麼

  • php-cgi是使用php實現cgi協議的cgi程序,可以用來管理php解釋器
  • php-cgi變更php.ini配置和需重啓php-cgi才能讓新的配置生效,不可以平滑重啓
  • 直接殺死php-cgi進程php就不能運行了

php-fpm

  • php-fpm是使用php編寫的php-fastcgi管理器,管理對象是php-cgi程序,不能說php-fpm是fastcgi進程的管理器,因爲fastcgi是個協議
  • 修改php.ini之後,php-cgi進程的確是沒辦法平滑重啓的。php-fpm對此的處理機制是新的worker用新的配置,已經存在的worker處理完手上的活就可以歇着了,通過這種機制來平滑過渡
  • php-fpm是對fastcgi協議的實現,是進程管理器,啓動時包括master和worker進程兩部分,master進程監聽端口,接收來自webserver請求,worker進程一般具有多個,每個worker進程都有一個cgi進程解釋器,用來執行php代碼。
  • php-fpm有兩種執行方式, 與Apache一樣,它的進程數也是可以根據設置分爲動態和靜態的,一種是直接開啓指定數量的php-fpm進程,不再增加或者減少;另一種則是開始的時候開啓一定數量的php-fpm進程,當請求量變大的時候,動態的增加php-fpm進程數到上限,當空閒的時候自動釋放空閒的進程數到一個下限。
  • php啓動和工作原理
    • 啓動phpfpm時,會啓動master進程,加載php.ini文件,初始化執行環境,並啓動多個worker進程。每次請求來時會將請求傳遞給worker進程進行處理
  • php平滑重啓原理
    • 每次修改完php.ini配置並重啓後,會啓動新的worker進程加載新的配置,而之前已經存在的進程會在工作完成之後銷燬,因此實現平滑重啓

PHP運行模式

CGI模式

  • 使用CGI程序將瀏覽器,web服務器,php解釋器連接起來進行數據交換的工具,目前主要用來做開發和調試
  • CGI方式在遇到連接請求(用戶請求)先要創建cgi的子進程,激活一個cgi進程,然後處理請求,處理完後結束這個子進程。這就是fork-and-execute模式。所以用cgi方式的服務器有多少連接請求就會有多少cgi子進程,子進程反覆加載是cgi性能低下的主要原因。當用戶請求數量非常多時,會大量擠佔系統的資源內存、cpu時間等,造成效能低下。

FASTCGI模式

  • 最主流的方式大量用於 分佈式高併發的環境中
  • nginx+php-fpm

Nginx

server {
    listen       80; #監聽80端口,接收http請求
    server_name  www.example.com; #一般存放網址,表示配置的哪個項目
    root /home/wwwroot/zensmall/public/; # 存放代碼的根目錄地址或代碼啓動入口
    index index.php index.html; #網站默認首頁
    
    #當請求網站的url進行location的前綴匹配且最長匹配字符串是該配置項時,按順序檢查文件是否存在,並返回第一個找到的文件
    location / {
          #try_files,按順序檢查文件是否存在,返回第一個找到的文件
          #$uri代表不帶請求參數的當前地址
          #$query_string代表請求攜帶的參數
          try_files   $uri $uri/ /index.php?$query_string; #按順序檢查$uri文件,$uri地址是否存在,如果存在,返回第一個找到的文件;如果都不存在,發起訪問/index.php?$query_string的內部請求,該請求會重新匹配到下面的location請求
    }
    
     #當請求網站的php文件的時候,反向代理到php-fpm去處理
    location ~ \.php$ {
          include       fastcgi_params; #引入fastcgi的配置文件
          fastcgi_pass   127.0.0.1:9000; #設置php fastcgi進程監聽的IP地址和端口
          fastcgi_index  index.php; #設置首頁文件
          fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name; #設置腳本文件請求的路徑
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章