FastCGI 為現有 CGI (共用閘道介面) 的增強版本,CGI 是外部應用程式與 Web 伺服器之間的介面標準。與 CGI 一樣,FastCGI 應用程式以獨立的隔離程序執行。使用 FastCGI 的一些優勢如下:
使應用程式能夠在用戶端請求之間能持續、免除+H204應用程式啟動的經常性耗用時間,並允許應用程式在用戶端呼叫之間維持狀態。
使應用程式能夠常駐在遠端系統 (與執行 Web 伺服器的系統不同) 上。
讓應用程式功能更靈活,明確支援執行用戶端認證的應用程式和支援輸入篩選功能。
讓管理員限制 FastCGI 伺服器對系統造成的影響。
FastCGI 外掛程式可讓 Web 伺服器以可延伸的方式,安全地與常用協力廠商動態內容產生技術 (例如 Perl 和 Python) 搭配作業。
如需有關 FastCGI 的更多資訊,請參閱 http://www.fastcgi.com/devkit/doc/fcgi-spec.html 上的規格。
FastCGI 外掛程式提供了下列伺服器應用程式函數 (SAF):
以下小節說明 FastCGI SAF 的各種參數和「error-reason」字串:
auth-fastcgi 是一個 PatchCheck 函數。此函數用於將請求轉寄至「Authorizer」FastCGI 應用程式。如果授權成功,將傳送回覆碼 200。否則,會將來自「Authorizer」FastCGI 應用程式的回應傳送回使用者代理程式。
您可以在 http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S6 找到有關 FastCGI 角色的更多資訊。
auth-fastcgi SAF 可接受的參數位於:FastCGI SAF 參數。
以下 obj.conf 程式碼範例說明 auth-fastcgi 的用法:
PathCheck fn="auth-fastcgi" app-path="/usr/bin/perl" app-args="/fastcgi/apps/auth/SimpleAuth.pl" bind-path="localhost:3432"。
responder-fastcgi 是一個 Service 函數。此函數用於將請求轉寄至做為「Responder」的 FastCGI 應用程式。來自 Responder 應用程式的回應將傳送回使用者代理程式。可以在 http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S6 找到有關 FastCGI 角色的更多資訊。
responder-fastcgi SAF 可接受的參數清單位於:FastCGI SAF 參數。
以下 obj.conf 程式碼範例說明 responder-fastcgi 的用法:
Service fn="responder-fastcgi" app-path="/fastcgi-enabled-php-installation/bin/php" bind-path="localhost:3433" app-env="PHP_FCGI_CHILDREN=8" app-env="PHP_FCGI_MAX_REQUEST=500"。
filter-fastcgi 是一個 Service 函數。此函數用於將請求轉寄至「Filter」類型的 FastCGI 應用程式。「Filter」應用程式可接收與 HTTP 請求關聯的資訊,還可以接收儲存在伺服器上的檔案中資料。然後,「Filter」應用程式產生「已篩選」版本的資料流做為回應。此回應將被傳送回使用者代理程式。可以在 http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S6 找到有關 FastCGI 角色的更多資訊。
filter-fastcgi SAF 可接受的參數清單位於:FastCGI SAF 參數。
以下 obj.conf 程式碼範例說明 filter-fastcgi 的用法:
Service fn="filter-fastcgi" app-path="/fastcgi/apps/filter/SimpleFilter" bind-path="localhost:3434" app-env="LD_LIBRARY_PATH=/fastcgi/fcgi-2.4/libfcgi/.libs" min-procs=2
error-fastcgi 是 Error 函數。error-fastcgi SAF 可處理 FastCGI 外掛程式特有的錯誤。但是,此函數並不處理 HTTP 錯誤。可將 FastCGI 外掛程式配置為發生錯誤時顯示特定頁面,或將請求重新導向至特定 URL。
error-fastcgi SAF 可接受的參數清單位於:FastCGI SAF 參數。
以下 obj.conf 程式碼片段示範 error-fastcgi 的用法:
Error fn="error-fastcgi" error-reason="Invalid Parameters" error-url="http://www.foo.com/errorPage.html"
請參閱FastCGI SAF 參數,以取得有關 error-fastcgi 參數的資訊。
除非另有明確說明,否則 FastCGI 外掛程式 SAF「auth-fastcgi」、「responder-fastcgi」和「filter-fastcgi」均可接受下列參數:
請注意,參數 chroot、user、group 和 nice 僅適用於 UNIX 平台。這些參數在 Windows 平台上會被忽略。
app-path - (可選擇) 處理請求的 FastCGI 應用程式路徑。此功能取決於 bind-path 參數的值,如下所示:
如果僅指定 app-path,則外掛程式將建立 FastCGI 應用程式,用於偵聽由外掛程式建立的 UNIX 網域通訊端。但是,僅 UNIX 平台接受此參數。在 Windows 上,會記錄一則錯誤訊息。
如果同時指定 app-path 和 bind-path,則外掛程式將啟動指定的 FastCGI 應用程式程序,並將其連結至指定的 bind-path。
如果僅指定 bind-path,則會將 FastCGI 應用程序視為遠端執行。因此,外掛程式將不會啟動 FastCGI 應用程式程序。
如果「app-path」和「bind-path」均未指定,則外掛程式將記錄一則錯誤訊息。
app-args — (可選擇) 當成引數傳送至 FastCGI 應用程式程序的值。您可使用多個 app-args 參數。使用多個 app-args 參數的格式為 app-args="value" app-args="value" ..。
bind-path - (可選擇) 可以是 Unix 網域通訊端名稱或「host:port」形式。「app-path」參數的說明解釋了「bind-path」參數的用法。請注意,Unix 網域通訊端名稱僅適用於 UNIX 平台。在 Windows 平台上,必須將 bind-path 指定為「host:port」。
min-procs - (可選擇) 用於指定要建立的 FastCGI 應用程式程序最小整數值。預設為 1。
max-procs - (可選擇) 用於指定可建立的 FastCGI 應用程式程序最大整數值。此整數值必須等於或大於 min-procs 值。預設為 1。
chroot - (可選擇) 用於設定 chroot FastCGI 伺服器應用程式程序的根目錄。預設為 Web Server 的根目錄。
user - (可選擇) 指定 FastCGI 應用程式執行時所用之身份的使用者 ID。預設為 Web Server 的使用者 ID。
group - (可選擇) FastCGI 應用程式將在指定的群組下執行。預設為 Web Server 的群組。
nice - (可選擇) 指定 FastCGI 應用程式程序的 nice/priority 值。
listen-queue - (可選擇) 用於指定通訊端的偵聽佇列大小整數值。此參數的預設值為 256。
app-env - (可選擇) 當成環境變數傳送至 FastCGI 應用程式程序的成對值。您可使用多個「app-env」參數。使用多個 app-env 參數的格式為 app-env="name=value" app-env="name=value"....。
reuse-connection - (可選擇) 一個布林值,用於確定是否重複使用與 FastCGI 應用程式的連線。False (0、false、no) 代表每次處理請求後需+H242關閉與 FastCGI 應用程式的連線。+H248True (1、true、yes) 代表新請求可重複使用現有連線。預設為 false。另請參閱 connection-timeout。
connection-timeout - (可選擇) 如果將「reuse-connection」設定為 True,則此值可指定池儲存的連線的逾時值 (以秒為單位)。如果連線閒置長達指定的時間長度,外掛程式將關閉此連線。此參數的預設值為 5 秒。另請參閱 reuse-connection。
resp-timeout - (可選擇) 代表 FastCGI 伺服器回應逾時的整數值 (以秒為單位)。如果在指定的時間內沒有來自 FastCGI 應用程式的回應,將捨棄此請求。此參數的預設值為 5 分鐘。
restart-interval - (可選擇) 值為一個整數,代表重新啟動 FastCGI 應用程式的時間間隔 (以分鐘為單位)。此參數的預設值為 60 分鐘 (1 小時)。如果將此參數的值設定為零,將不會強制 FastCGI 應用程式重新啟動。
req-retry - (可選擇) 值為一個整數,代表 FastCGI 應用程式拒絕請求時,外掛程式應重新傳送請求的次數。此參數的預設值為零。
error-fastcgi 伺服器應用程式功能 (SAF) 接受下列參數:
error-url - 指定在發生失敗或錯誤情況時,要顯示的頁面、URI 或 URL。此參數的值可以是絕對路徑、文件根的相對路徑、URL 或 URI。
error-reason - (可選擇) 代表 FastCGI 協定錯誤的字串。發生任何外掛程式錯誤時,此字串可區分要顯示的錯誤 URL。
本節提供所有有效「error-reason」字串的清單及這些字串的說明:
「缺少配置參數或配置參數無效」:未指定 app-path 和 bind-path 時。
「Stub 啟動錯誤」:無法啟動 Fastcgisub 程序。
「Stub 連線失敗」:無法連線至 Fastcgistub。
「無權限」:FastCGI 應用程式或 Fastcgisub 沒有執行權限。
「Stub 請求處理錯誤」:無法將請求傳送至 stub、接收到的請求無效,或 stub 沒有針對請求傳送回應等。
「設定參數失敗」:設定 user、group、chroot、nice 等失敗。
「使用者和/或群組無效」:使用者或群組無效。
「伺服器程序建立失敗」:FastCGI 應用程式執行失敗或 FastCGI 應用程式無法連結至指定的位址。
「Fastcgi 協定錯誤」:FastCGI 應用程式包含具有無效 FastCGI 版本或角色的標頭。
「內部錯誤」:無法開啟要傳送至篩選應用程序的檔案,或任何其他不明的錯誤。
FastCGI 外掛程式隨附於 Web Server 7.0。外掛程式安裝在以下位置:
32 位元的 FastCGI 外掛程式二進位檔安裝在 <install_dir>/plugins/fastcgi 目錄下。 |
64 位元的 Solaris SPARC FastCGI 外掛程式二進位檔安裝在 <install_dir>/lib/plugins/fastcgi/64 目錄下。 |
將安裝下列 FastCGI 二進位檔:
libfastcgi.so (適用於 Solaris/Linux) |
fastcgi.dll(適用於 Windows) |
Fastcgistub.exe(適用於 Windows) |
libfastcgi.sl(適用於 HP-UX) |
Fastcgistub(可執行檔) |
配置 FastCGI 外掛程式時,需使用位於 <instance-dir>/config 目錄下的 Web Server 配置檔案。若要配置 FastCGI 外掛程式,請執行下列步驟:
使用「load-modules」Init 函數載入 FastCGI 外掛程式共用程式庫。
Init fn=flex-init access="access" format.access="%Ses->client.ip% - %Req->vars.auth-user% [%SYSDATE%] \"%Req->reqpb.clf-request%\" %Req->srvhdrs.clf-status% %Req->srvhdrs.content-length%" Init fn="load-modules" shlib="libJava EEplugin.so" shlib_flags="(global|now)" Init fn="load-modules" shlib="libfastcgi.so" shlib_flags="(global|now)"
編輯 mime.types 檔案以指定 MIME 對映。修改 MIME 類型對映是可選步驟。
例如,
#--Sun Microsystems Inc. MIME 資訊 # 請勿刪除上一行。該行用於識別檔案類型。 # # Copyright 2006 Sun Microsystems, Inc. 版權所有。 # 使用應遵守授權合約的條款。 # type=application/octet-stream exts=bin type=application/astound exts=asd,asn ... ... type=magnus-internal/fastcgi exts=php ... ...
編輯 obj.conf 檔案,以使用之前各節所述的外掛程式 SAF,來配置 FastCGI 特有的請求。
修改後的 obj.conf 檔案範例如下所示:
# # Copyright 2006 Sun Microsystems, Inc. 版權所有。 # 使用應遵守授權合約的條款。 # # 您可以編輯此檔案,但如果使用管理 GUI 或 CLI, # 註釋和格式變更可能會遺失。 <object name = "default"> AuthTrans fn="match-browser" browser="*MSIE*" ssl-unclean-shutdown="true" NameTrans fn="ntrans-Java EE" name="Java EE" NameTrans fn="pfx2dir" from="/mc-icons" dir="/ws7/lib/icons" name="es-internal" NameTrans fn="assign-name" from="/fcgi/*" name="fcgi.config" </object> <Object name="fcgi.config"> AuthTrans fn="auth-fastcgi" app-path="/fastcgi/apps/c/simpleAuth" bind-path="localhost:2111" Service fn="responder-fastcgi" app-path="/fastcgi_enabled_php_installation_dir/bin/php" app-env="name1=abc" </object> ...
請注意,針對不同的 URL 式樣定義不同的物件或將 SAF 對映至不同的 MIME 類型,便可以不同的方式呼叫 FastCGI SAF。
如需有關 obj.conf 配置及語法的更多資訊,請參閱「Administration Configuration File Reference Guide」。
Fastcgistub 是一個程序管理程式,用於管理 FastCGI 應用程式程序的生命週期。Fastcgistub 將其訊息記錄至 Web Server 暫存目錄下的 Fastcgistub.log 檔案中。發生任何錯誤時,檢查此檔案有助於消除問題。
問題:FastCGI 請求未得到處理
可能的原因及解決方案如下:
請檢查是否載入 FastCGI 外掛程式。如果在啟動 Web Server 期間出現下列訊息,則表示已成功載入外掛程式。另外,請檢查 magnus.conf 中外掛程式程式庫的路徑: FCGI1000: Sun Java System Web Server 7.0 FastCGI NSAPI Plugin < build info>
請檢查在 obj.conf 中是否正確指定請求對映。如需有關 obj.conf 檔案的更多資訊,請參閱「Sun Java System Web Server Administrator's Configuration Reference File」。
請檢查錯誤記錄中的任何可能錯誤訊息。
請檢查 stub 二進位檔及 FastCGI 應用程式的權限。如果未授予足夠的權限,則外掛程式將無法啟動 stub 或應用程式。有關
請檢查 Fastcgistub.log 檔案中有關 stub 端的任何可能錯誤。
如果可能,請以獨立模式執行 FastCGI 應用程式,檢查該應用程式是否能夠正確無誤地執行。
如果丟出任何程式庫相依性錯誤,請在 obj.conf 中將 LD_LIBRARY_PATH 指定為 app-env 參數,且參數具有 LD_LIBRARY_PATH=<>相依性程式庫路徑值。
問題:FastCGI 應用程式未啟動。
可能的原因及解決方案如下:
請檢查 Fastcgistub.log 檔案中的下列記錄訊息: |
.. <pid> process startup failure, trying to restart ... Even after trying <n> time(s), <application path> process failed to start...no more retries
啟動失敗的原因之ㄧ可能是由於無法載入相依性程式庫。此問題可透過以下方式解決:將適當的程式庫路徑當成 app-env 參數值,指定給 obj.conf 檔案中配置的 FastCGI 應用程式。例如︰
Service fn="responder_fastcgi" app-path="/fastcgi/c/tux-app" bind-path="localhost:2112" app-env="LD_LIBRARY_PATH=/tuxedo/lib" |
您可以使用 Perl、PHP、C 和 Java 開發 FastCGI 應用程式。下列小節簡要說明使用一些常用程式設計語言開發應用程式的程序。
一般 FastCGI 應用程式具有以下程式碼結構:
Initialization code Start of response loop body of response loop End of response loop
初始化程式碼僅在應用程式初始化時執行一次。初始化程式碼通常執行一些耗時作業,例如開啟資料庫或者計算表格或點陣圖的值。將 CGI 程式轉換為 FastCGI 程式的主要作業,是區分初始化程式碼與針對每個請求都需要執行的程式碼。
回應迴圈會持續執行,等待用戶端請求到達。迴圈以呼叫 FCGI_Accept (FastCGI 程式庫中的常式) 開頭。FCGI_Accept 常式將封鎖程式執行,直到用戶端請求 FastCGI 應用程式為止。收到用戶端請求時,FCGI_Accept 將解除封鎖、執行回應迴圈主體的一次重複運算,之後再次封鎖,等待另一個用戶端請求。僅當系統管理員或 Web Server 終止 FastCGI 應用程式時,該迴圈才會終止。
從 CPAN 下載並安裝最新的 FCGI 模組。以 ActivePerl 而言,您可以從 http://aspn.activestate.com/ASPN/Downloads/ActivePerl/PPM/Zips 下載模組。
如需有關使用 Perl 撰寫 FastCGI 應用程式的更多資訊,請參閱 http://www.fastcgi.com/devkit/fastcgi-prog-guide/ch3perl.htm#3659
從 PHP 4.3.0 開始,FastCGI 成為 PHP 引擎支援的配置。若要編譯支援 FastCGI 之 PHP 4.3.x 或更高版本的引擎,請將配置切換 --enable-fastcgi 納入建立程序,例如
./configure <other-options> --enable-fastcgi gmake |
編譯完成後,php 二進位檔將啟用 FastCGI。
當使用 PHP 版本 5.1.2 或舊版 (包括 PHP 4.x) 時,應使用 host:port 格式配置 FastCGI 外掛程式。例如,bind-path = “localhost:3333”。
對於 PHP 版本 5.1.3 及更高版本,bind-path 是可選擇的。如果已指定,則不應使用「host:port」格式。它可以是一個字串。例如,bind-path = “myphpbindpath”。
FastCGI 開發工具組提供撰寫 FastCGI C/Java 應用程式的 API。您可以從 http://www.fastcgi.com/devkit/doc/fcgi-devel-kit.htm 下載此工具組。
若要建立下載的 FastCGI 開發套件,請執行下列步驟:
如需有關使用 C 撰寫 FastCGI 應用程式的更多資訊,請參閱 http://www.fastcgi.com/devkit/doc/fcgi-devel-kit.htm#S3
如需有關使用 Java 撰寫 FastCGI 應用程式的更多資訊,請參閱 http://www.fastcgi.com/devkit/doc/fcgi-java.htm
本節包含使用 PHP、Perl 和 C 撰寫的 FastCGI 應用程式範例。
<?php $dir = "/tmp/"; // Open a known directory, and proceed to read its contents if (is_dir($dir)) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { echo "filename: $file : filetype: " . filetype($dir . $file) . "\n"; } closedir($dh); } } ?>
上述範例的 obj.conf 程式碼片段:
<Object name="default"> NameTrans fn="assign-name" from="/fcgi/*" name="responder.fcgi" </Object> <Object name="responder.fcgi"> Service fn="responder-fastcgi" app-path="/foo/fastcgi-enabled-php-installation/bin/php" bind-path="localhost:3431" min-procs=3 </Object>
#!/usr/bin/perl use FCGI; while (FCGI::accept >= 0) { if( $ENV{'HTTP_AUTHORIZATION'} ) { # This value can be further decoded to get the actual username and password and then # perform some kind of user validation. This program only checks for the presence of # of this environment param and is not really bothered about its value print( "Status: 200\r\n" ); print( "\r\n" ); } else { print( "Status: 401\r\n" ); print( "WWW-Authenticate: basic realm=\"foo\"\r\n" ); print( "\r\n" ); } } Example obj.conf settings for the above example:
上述範例的 obj.conf 程式碼片段:
<Object name="responder.fcgi"> AuthTrans fn="auth-fastcgi" app-path="/fastcgi/apps/auth/SimpleAuth.pl" bind-path="localhost:3432" Service fn="responder-fastcgi" app-path="/foo/fastcgi-enabled-php-installation/bin/php" bind-path="localhost:3433" app-env="PHP_FCGI_CHILDREN=8" min-procs=1 </Object>
第一次向 http://localhost/fcgi/php/ListDir.php 提出請求時,瀏覽器會顯示認證對話方塊。在使用者輸入使用者名稱和密碼後,即會列出「/tmp」目錄內容。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcgi_stdio.h> void main(void) { size_t PageSize = 1024 * 3; char *page; FCGX_Stream *in, *out, *err; FCGX_ParamArray envp; int count=0; page = (char *)malloc(PageSize); if (page == NULL) { printf("Content-type: text/x-server-parsed-html\r\n"); printf("<title>malloc failure</title>"); printf("<h1>Cannot allocate memory to run filter. exiting</h1>"); printf("\r\n\r\n"); exit(2); } while(FCGI_Accept() >= 0) { char *tmp; char *execcgi; char *dataLenStr = NULL; int numchars = 0; int stdinDataSize = 0; int filterDataLen = 0; int dataToBeRead = 0; int x = 0; int loopCount = 0; count++; dataLenStr = getenv("FCGI_DATA_LENGTH"); if(dataLenStr) filterDataLen = atoi(dataLenStr); /* clear out stdin */ while (EOF != getc(stdin)) { stdinDataSize++; } dataToBeRead = filterDataLen; FCGI_StartFilterData(); tmp = page; /** just in case fread or fwrite moves our pointer **/ //start responding printf("Content-type: text/plain\r\n"); printf("\r\n"); /** send a new line at the beginning **/ printf("<title>SIMPLE FILTER</title>"); printf(<h1>This page was Filtered by SimpleFilter FastCGI filter</h1>"); printf("file size=%d<br>", filterDatalen); printf("stdin size=%d<br>, stdinDataSize); while(dataToBeRead > 0 ) { x = 0; page = tmp; if(dataToBeRead > PageSize) x = PageSize; else x = dataToBeRead; numchars = fread((void *)(page), 1, x, stdin); if( numchars == 0 ) continue; /** at this point your data is in page pointer, so do whatever you want with it before sending it back to the server. In this example, no data is manipulated. Only the count of number of times the filter data is read and the total bytes read at the end of every loop is printed. **/ dataToBeRead -= numchars; loopCount++; printf("loop count = %d ... so far read %d bytes <br>", loopCount, (filterDatalen - dataToBeRead)); } printf("\r\n\r\n"); /** send a new line at the end of transfer **/ fflush(stdout); page = tmp; /** restore page pointer **/ memset(page,NULL,numchars); } free(page); }
上述範例的 obj.conf 設定範例。
如果此 FastCGI 應用程式和 Web Server 在同一台機器上執行,則
<Object name=<"filter.fcgi"> Service fn="filter-fastcgi" app-path="/fastcgi/apps/filter/SimpleFilter.exe" bind-path="localhost:3434" app-env="LD_LIBRARY_PATH=/fastcgi/fcgi-2.4/libfcgi/.libs" </Object>
如果該應用程式是在遠端機器上執行,則 obj.conf 檔案中必須包含下列程式碼行:
<Object name="filter.fcgi"> Service fn="filter-fastcgi" bind-path="<remote-host>:<remote-port>" </Object>
如果要篩選位於 fcgi 目錄 (此目錄位於 Web Server 實例的文件根目錄下) 下大小為「26868」位元組的檔案「FilterThisFile」,則向「http://localhost/fcgi/filter/FilterThisFile」提出請求時,會產生下列輸出:
This page was Filtered by SimpleFilter FastCGI filter
file size = 26868 |
stdin size = 0 |
loop count = 1... so far read 3072 bytes |
loop count = 2... so far read 6144 bytes |
loop count = 3... so far read 9216 bytes |
loop count = 4... so far read 12288 bytes |
loop count = 5... so far read 15360 bytes |
loop count = 6... so far read 18432 bytes |
loop count = 7... so far read 21504 bytes |
loop count = 8... so far read 24576 bytes |
loop count = 9... so far read 26868 bytes |