分類  >  Web前端 >

【Web學習札記】淺析CGI概念及用法

tags:    時間:2013-12-09 23:33:57
【Web學習筆記】淺析CGI概念及用法
1. CGI是什麼
        CGI是Common Gateway Interface的簡寫,它提供了一種標準方法使得位於WebServer後端的web應用可以根據client的請求動態生成網頁內容。在互聯網應用常見的C-S模式中,從Server角度來看,CGI提供了WebServer和生成具體內容的Web程序之間的介面,具體實現CGI標準協議的程序稱為CGI腳本(因為它們通常是用腳本語言實現的)或簡稱CGI。
        可見,嚴格意義上的CGI其實是一個標準(詳見CGI-RFC-Doc),而我們經常聽到的CGI其實是指實現CGI標準的CGI程序(可能由腳本語言實現,也可能由C/C++實現)
        對於新手來說,有必要搞清楚CGI的這兩重概念,否則可能由於概念不清而導致一頭霧水。
        關於初學者對CGI的困惑,StackOverflow上有篇有趣且經典的帖子,強烈建議圍觀:I never really understood: what is CGI? ,相信對理解CGI的兩重概念有幫助。

2. 引入CGI的目的
        CGI標準定義了一系列被稱為meta-variables的抽象參數,這些meta-variables可描述來自客戶端的http請求,從而實現了一個WebServer和後端CGI程序的介面,這個介面是與平台無關的。
        由於CGI的存在,WebServer與後端程序得以各司其職:
         1) WebServer負責處理HTTP連接、數據傳輸、網路事件等與客戶端請求相關但與具體應用無關的邏輯
         2) 後端程序處理應用相關邏輯,根據請求參數動態生成數據並由WebServer返回給客戶端
        一個典型C-S交互的完整流程如下所述:
        WebServer接收來自client的請求並將其請求參數轉換為CGI的meta-variables和message-body(如HTTP POST的body數據),接著,根據URI參數來選擇合適的CGI程序並調用之以處理用戶請求,然後,接收CGI程序返回的結果數據,最後,將數據返回給client。
        需要說明的是:在處理client request過程中,WebServer負責實現協議級或傳輸層的安全認證(如https認證)。

3. 實例說明
        以client的http GET請求http://somehost.com/cgi-bin/somescript/this%2eis%2epath%3binfo?param1=hello&param2=world為
例,其可以被抽象為如下格式:
           <scheme> "://" <server-name> ":" <server-port> <script-path> <extra-path> "?" <query-string>
        根據CGI標準,位於WebServer下游的CGI程序會將該http請求轉換為CGI標準定義的一系列meta-variables,例如:
         <scheme>:值為"http",對應meta-variables中的SERVER_PROTOCOL
         <server-name>:值為"somehost.com",對應SERVER_NAME
         <server-port>:默認值80,對應SERVER_PORT
         <script-path>:值為"/cgi-bin/somescript/",對應SCRIPT_NAME
         <extra-path>:值為"this%2eis%2epath%3binfo",實際上,它是另一個meta變數PATH_INFO的url-encoded形式
         <query-string>:值為param1=hello&param2=world,對應QUERY_STRING
        由於CGI程序已經將http請求轉換為標準的CGI meta varialbes,故不管後端業務模塊是什麼語言實現的,它不用再去關心具體的
http請求需要怎麼解析,只需訪問這些meta變數並做對應處理即可。這正是CGI標準及CGI程序的意義所在。

4. 關於CGI的補充說明
       傳統CGI腳本其實是一段可執行程序,每次執行都會創建新進程。這樣就引起一個問題:webserver每次響應client請求,均需創建並運行CGI進程后才能返回結果。在Linux系統中,創建進程的代價是比較高的,尤其是生產環境要求高併發且低延時的情況下,新建進程對系統性能的影響會更加明顯。
       在這種現實驅動下,出現了兩種常見的優化思路:
       1) 預先創建(prefork)一系列CGI進程,從而避免每次新建進程。典型代表:FastCGI 
       2) 業務代碼直接以擴展模塊的形式嵌入WebServer執行。典型代表:Apache或Nginx的mod_php擴展等

5. CGI實際部署示例
        以lighttpd為例,只需在lighttpd.conf中做兩處配置即可:
        1) 在webserver要載入的擴展模塊中指定"mod_proxy_backend_fastcgi",示例如下:

## modules to load # at least mod_access and mod_accesslog should be loaded # all other module should only be loaded if really neccesary # - saves some time # - saves memory server.modules = (        "mod_access",       "mod_expire",       "mod_accesslog",       "mod_error_redirect",       "mod_cookie",       "mod_firewall",       "mod_deflate",       "mod_rewrite",       "mod_proxy_core",       "mod_proxy_backend_fastcgi",       "mod_redirect" )
       2) 指定webserver向後端模塊轉發協議為CGI協議,示例如下:
$HTTP["url"] =~ "\.php" {       proxy-core.balancer = "static"       proxy-core.allow-x-sendfile = "enable"       proxy-core.protocol = "fastcgi"     }

【參考資料】
1. wikipedia - Common Gateway Interface 
2. RFC3875 - The Common Gateway Interface (CGI) Version 1.1  
3. CGI Programming Is Simple! 
4. StackOverflow - I never really understood: what is CGI? 
5. wikipedia - FastCGI 

======================= EOF ========================


推薦閱讀文章

Bookmark the permalink ,來源:互聯網