一步步領悟 CGI FastCGI PHP-FPM 的真正奧義
來自: http://mengkang.net/664.html
CGI 模型
CGI 是外部應用程序( CGI 程序)與 Web 服務器之間的接口標準,是在 CGI 程序和 Web 服務器之間傳遞信息的規程。
圖片來源 http://mengkang.net/491.html
CGI 核心就是其定義的環境變量。
SERVER_NAME:運行CGI序為機器名或IP地址。 SERVER_INTERFACE:WWW服務器的類型,如:CERN型或NCSA型。 SERVER_PROTOCOL:通信協議,應當是HTTP/1.0。 SERVER_PORT:TCP端口,一般說來web端口是80。 HTTP_ACCEPT:HTTP定義的瀏覽器能夠接受的數據類型。 HTTP_REFERER:發送表單的文件URL。(并非所有的瀏覽器都傳送這一變量) HTTP_USER-AGENT:發送表單的瀏覽的有關信息。 GETWAY_INTERFACE:CGI程序的版本,在UNIX下為 CGI/1.1。 PATH_TRANSLATED:PATH_INFO中包含的實際路徑名。 PATH_INFO:瀏覽器用GET方式發送數據時的附加路徑。 SCRIPT_NAME:CGI程序的路徑名。 QUERY_STRING:表單輸入的數據,URL中問號后的內容。 REMOTE_HOST:發送程序的主機名,不能確定該值。 REMOTE_ADDR:發送程序的機器的IP地址。 REMOTE_USER:發送程序的人名。 CONTENT_TYPE:POST發送,一般為application/xwww-form-urlencoded。 CONTENT_LENGTH:POST方法輸入的數據的字節數。
Web 服務器在接受請求之后對這些環境變量賦值,然后創建一個子進程,在子進程中 CGI 程序通過這些環境變量取值。這個過程就是對 CGI 接口的實現。
舉個例子以 C 為 Web 服務器,PHP 作為 CGI 程序。
1. Web 啟動 Socket 監聽之后,接受到一個客戶端的請求
GET /cgi-demo.php?a=b&c=d HTTP/1.1 Host: localhost:9003 Connection: keep-alive Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4,ja;q=0.2
2. Web 服務器就可以給環境變量賦值了
REQUEST_METHOD GET QUERY_STRING a=b&c=d SCRIPT_NAME /cgi-demo.php SERVER_PROTOCOL HTTP/1.1 SERVER_NAME localhost SERVER_PORT 9003
3. CGI 程序解析獲取這些環境變量
#include <stdio.h>include <stdlib.h>
include <unistd.h>
int main() { putenv("QUERY_STRING=a=b&c=d");
int pid = fork();
if (pid == 0) { system("php cgi-demo.php"); }
return 0; }</pre>
cgi-demo.php 則在子進程中獲取到 web 服務器在父進程設置的環境變量
<?php printf("QUERY_STRING:%s\n", getenv("QUERY_STRING"));上面這兩段代碼僅僅是演示 Web 服務器和 CGI 程序對 CGI 接口的實現,對數據的輸入輸出都省略沒寫。完整的Web 服務器 + CGI 程序demo 可以參考 http://mengkang.net/491.html
FastCGI 模型
![]()
FastCGI 的核心則是取締傳統的 fork-and-execute 方式,減少每次啟動的巨大開銷,以常駐的方式來處理請求。區別于傳統的 CGI 是執行腳本從環境變量中換取 CGI 接口定義的值,而 FastCGI 則又多了一層 socket 服務的交互,Web 服務器需要將 CGI 接口數據封裝在遵循 FastCGI 協議包中發送給 FastCGI 解析器程序。正式因為 FastCGI 進程管理器是基于 socket 的,所以也是分布式的,所以 Web 服務器和 CGI 程序可以分布部署。
coding...
PHP-FPM
coding...
大概的介紹可以看
http://www.php-internals.com/book/?p=chapt02/02-02-03-fastcgi
FastCGI協議規范
http://www.fastcgi.com/devkit/doc/fcgi-spec.html
http://andylin02.iteye.com/blog/648412 (中文版)
FastCGI 進程管理器的 PHP 簡單實現