摘要:原文開發(fā)之介紹和環(huán)境搭建由于需要做一些簡單的基于的開發(fā),開始學習和調研,本篇介紹和的概念以及基于官方的,以及搭建起簡單的開發(fā)環(huán)境,以作備忘。所以程序其實沒有語言限制,只要能夠讀取環(huán)境變量,讀寫標準輸入輸出即可。管理器有多種形式。
原文:FastCGI+lighttpd開發(fā)之介紹和環(huán)境搭建
由于需要做一些簡單的基于FastCGI的Web開發(fā),開始學習和調研,本篇介紹CGI和FastCGI的概念以及基于FastCGI官方的devkit,以及l(fā)ighttpd搭建起簡單的開發(fā)環(huán)境,以作備忘。
為啥要搞這個?現(xiàn)在開發(fā)Web有N種選擇,啥php,C#,java,ruby,nodejs...哪個都比開發(fā)FastCGI要簡單和強大的多,為何還要跑到這么個底層來做Web服務呢?答案是嵌入式系統(tǒng)需求!我們知道嵌入式系統(tǒng)往往由于硬件的限制,為了節(jié)約處理器和內存,很多事情都需要省的點用。對于簡單的Web服務,沒有必要(或者不能)去使用高層次的編程框架,那么這個時候,就可以直接基于CGI那套協(xié)議來進行開發(fā)。通常在這個層次下,C語言是首選。
FastCGI和CGI的概念要搞清楚FastCGI,必須先搞清楚CGI
參考
CGI與FastCGI
Nginx + CGI/FastCGI + C/Cpp
搞不清FastCgi與PHP-fpm之間是個什么樣的關系
CGICGI是一種協(xié)議,用于擴展Web服務器原本的能力。我們知道,Web服務器最早是用來提供靜態(tài)文件訪問的,想要實現(xiàn)動態(tài)內容提供是比較困難的。CGI因此而產生。這是一套協(xié)議,簡單的說,就是Web服務器在必要的時候,為了處理Request,會調起一個進程(CGI程序),讓這個進程來處理請求,并將這個進程返回的結果返回給客戶端。然后進程結束,下次請求重復這個過程。這個過程中涉及到Web進程和CGI程序進程的輸入和輸出協(xié)議,這個機制和協(xié)議就叫CGI。那么具體的說,在CGI程序中,輸入和輸出是通過stdin,stdout,stderr來進行的,請求的參數(shù)等則是通過環(huán)境變量來傳遞的。所以CGI程序其實沒有語言限制,只要能夠讀取環(huán)境變量,讀寫標準輸入輸出即可。下圖以Apache和Python為例,說明CGI的工作方式
Python的CGI擴展能夠在Python解釋器的幫助下,解釋用戶編寫的Python腳本,從而輸入輸出,雖然這個模型相比上面闡述的基本模型要復雜一點,但是本質是相同的。
CGI的缺點很明顯,每個請求都要啟動進程來處理請求,進程啟動的開銷是沒有必要的。
FastCGI為了解決CGI的缺點,誕生了FastCGI。既然CGI的缺點是進程的頻繁啟動和關閉,那么是否可以有一個專門管理CGI進程的程序,在沒有Request請求的情況下,保持多個CGI進程的掛起狀態(tài),當有請求的時候,分配一個進程來處理,處理完成后掛起,就像是進程池一樣。這個進程池的管理程序稱為FastCGI管理器,從字面看,它可以提高CGI程序的效率。
不光是處理模型的優(yōu)化,CGI程序只能在Web服務器本機執(zhí)行,而基于FastCGI的管理下,CGI程序可以被部署在遠程,通過TCP Socket或者Unix domain Socket來傳輸數(shù)據(jù),這種模式可以理解為FastCGI代理。
FastCGI管理器有多種形式。例如:Apache和Lighttpd是通過模塊的方式實現(xiàn)FastCGI管理器的,而Nginx則是通過FastCGI代理模式實現(xiàn)的(也就是說需要一個多帶帶的FastCGI管理器進程,該進程通過偵聽TCP Socket或者Unix domain Socket在Nginx和CGI程序之間起到橋梁作用)。
同樣是Apache和Python為例,下圖為FastCGI的啟動和運行的模型
Apache在調用用戶腳本的時候,會依靠Apache內建的FastCGI模塊來調度CGI進程,CGI進程也不會消亡,下次請求就不需要重新啟動解析器了。而且CGI進程是通過Socket形式實現(xiàn)輸入輸出的,當然CGI程序在編寫的時候,仍然是通過stdin,stdout,stderr來輸入輸出,只是最終可能是通過網(wǎng)絡來實現(xiàn)的,這樣做可以實現(xiàn)從CGI程序到FastCGI程序的平滑過渡。你會發(fā)現(xiàn)開發(fā)FastCGI程序跟開發(fā)CGI程序并沒有多少區(qū)別。
關于Nginx的FastCGI代理模式,有必要多說幾句。Nginx自身沒有實現(xiàn)FastCGI管理器,但是Nginx可以支持FastCGI代理,我們來看看Nginx是如何配置php的就明白了:
location ~ .php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; include fastcgi_params; }
可以看到,Nginx其實是把請求扔給127.0.0.1:9000,那么還需要一個程序來監(jiān)聽127.0.0.1:9000啊,對了!這個程序就是php-fpm,所以我們在用Nginx配置php的時候需要:
php-fpm start
php-fpm可以幫Nginx實現(xiàn)CGI進程管理器的功能。看起來好麻煩有沒有,為什么Apache無需php-fpm,原因上面說了,Apache是通過模塊實現(xiàn)的,無需多帶帶啟動php-fpm。
那么,如何開始開發(fā)一個FastCGI程序呢,我們需要FastCGI的開發(fā)套件,以及一個合適的Web服務器,這里FastCGI套件從這里下載,Web服務器,我們選擇了lighttpd,因為既然要直接開發(fā)CGI程序,那么通常你會選擇盡可能輕量的Web服務器。當然支持FastCGI的Web服務器很多,這里有列表。
準備lighttpdlighttpd的安裝就不多說了,你可以選擇編譯安裝或者源安裝,我選擇了編譯安裝,所以后續(xù)的啟動啥的麻煩一點。
lighttpd的啟動和重啟如果是編譯安裝的,那么你需要將源碼包doc里面的config文件夾復制到/etc下,并重命名為lighttpd,這里面是lighttpd的一系列啟動配置,然后像下面這樣啟動:
/usr/local/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf
如果你經(jīng)常折騰Web服務器,這應該很好理解。當然你可以查看一下配置文件,了解個大概(尤其是日志文件的位置),由于配置文件有很多注釋,分享一個命令,能去掉注釋部分,只看重點:
sed -n "/^s*[^#]/p" /etc/lighttpd/lighttpd.conf
重啟的話,可以通過下面命令先殺掉相關的進程,然后再啟動
killall lighttpd /usr/local/sbin/lighttpd -f /etc/lighttpd/lighttpd.conflighttpd配置fastcgi模塊
這個相對簡單,在/etc/lighttpd/modules.conf,將里面的fastcgi模塊的引用反注釋掉
include "conf.d/fastcgi.conf"
那么關于fastcgi的配置就順理成章的在conf.d/fastcgi.conf中了,其中關鍵的一句是:
server.modules += ( "mod_fastcgi" )
底下有很多示例配置,尤其是對php的配置示例,尤其詳細,然而我們是直接做CGI程序,可以參考這個配置
fastcgi.debug = 1 fastcgi.server = ( ".fcgi" => ( "local" => ( "socket" => socket_dir + "fcgitest-fcgi.socket", "checklocal" => "disable", "bin-path" => server_root + "/htdocs/cgi-bin/fh.fcgi", "idle-timeout" => 10, "min-procs" => 1, "max-procs" => 1 ) ) )
理解了FastCGI原理后,再來看這個其實很容易理解:
對所有.fcgi后綴的處理
通過fcgitest-fcgi.socket
用/htdocs/cgi-bin/fh.fcgi程序來處理
最多同時駐留1個CGI進程,最少1個(對于嵌入式系統(tǒng),并不是要處理高并發(fā),多個進程并沒有意義)
我們可以通過瀏覽器訪問http://localhost/cgi-bin/fh.fcgi,即可執(zhí)行fh.fcgi程序(這里htdocs是配置的文檔根目錄)。
那么接下來的重點是開發(fā)/htdocs/cgi-bin/fh.fcgi程序。
開始開發(fā)FastCGI程序 開發(fā)套件的安裝下載好套件后,解壓在fcgi-devel-kit目錄
cd fcgi-devel-kit ./configure make cd libfcgi make make install
顯然我們其實需要的是FastCGI的include和lib,上面的命令可以在/usr/local/lib下創(chuàng)建幾個相關的庫文件:
-rw-r--r--. 1 root root 204902 Nov 15 20:09 libfcgi.a -rwxr-xr-x. 1 root root 704 Nov 15 20:09 libfcgi.la lrwxrwxrwx. 1 root root 16 Nov 15 20:09 libfcgi.so -> libfcgi.so.0.0.0 lrwxrwxrwx. 1 root root 16 Nov 15 20:09 libfcgi.so.0 -> libfcgi.so.0.0.0 -rwxr-xr-x. 1 root root 145320 Nov 15 20:09 libfcgi.so.0.0.0
.a是靜態(tài)庫,.la是基于libtool的鏈接庫。后面你可以選擇使用.a來鏈接,也可以使用libtool工具,使用.la來構建。
完成套件的安裝后,先創(chuàng)建一個項目文件,并將include和libtool工具拷貝進去(如果你不打算用libtool編譯,可以不拷貝libtool)
mkdir -p ~/Projects/fh cp -r ~/fcgi-devel-kit/include ~/Project/fh/fcgi_inc cp ~/fcgi-devel-kit/libtool ~/Project/fh/libtool
創(chuàng)建一個main.c文件,并編輯如下:
#include#include int main(){ int count = 0; while(FCGI_Accept() >= 0){ printf("Content-type: text/html " " " " FastCGI Hello! (C, fcgi_stdio library) " "FastCGI Hello! (C, fcgi_stdio library)
" "Request number %d running on host %s ", ++count, getenv("SERVER_NAME")); } }
上面的程序跟普通的CGI程序的關鍵區(qū)別在于while(FCGI_Accept() >= 0),這個條件會在沒有請求需要處理的時候阻塞,那么進程就會掛起,并在正常情況下不會退出。這樣就實現(xiàn)了進程駐留的效果。
編譯和鏈接使用libtool進行編譯和鏈接
./libtool --mode=compile gcc -I fcgi_inc -c main.c rm -f .libs/main.lo gcc -I fcgi_inc -c main.c -fPIC -DPIC -o .libs/main.lo gcc -I fcgi_inc -c main.c -o main.o >/dev/null 2>&1 mv -f .libs/main.lo main.lo
編譯得到的是main.lo和main.o,前者用于繼續(xù)用libtool鏈接FastCGI的lib,后者可用于普通的鏈接。
接著鏈接:
./libtool --mode=link gcc -o fh main.lo /usr/local/lib/libfcgi.la gcc -o fh main.o /usr/local/lib/libfcgi.so -lnsl -Wl,--rpath -Wl,/usr/local/lib -Wl,--rpath -Wl,/usr/local/lib
得到的程序fh,是通過main.o和/usr/local/lib/libfcgi.so鏈接后生成的(動態(tài)鏈接),可以看到libtool實際上只是對gcc的一個包裝而已。據(jù)說是為了方便解決依賴庫,筆者折騰了好久才弄清楚。
最后,將fh復制到目標目錄,并重命名。當然如果fh.fcgi進程已經(jīng)由lighttpd啟動,需要殺掉進程,再覆蓋。
cp -f fh /srv/www/htdocs/cgi-bin/fh.fcgi
最后使用瀏覽器的訪問效果:
需要注意的是,訪問的文件還是必須物理存在的(因為沒有配置任何rewrite),比如這里訪問的cgi-bin/fg.fcgi,實際上映射了/srv/www/htdocs/cgi-bin/fg.fcgi文件,然后再用fastcgi的方式來處理。否則只會返回404,筆者在這里卡了一下。
結語花了一天時間,簡單實驗的FastCGI的開發(fā),后續(xù)還需要使用IDE來開發(fā),并實現(xiàn)交叉編譯,后面再折騰了。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/21223.html
摘要:當客戶端請求到達時,進程管理器選擇并連接到一個解釋器。什么是是一個管理器,是只用于的可以在下載得到其實是源代碼的一個補丁,旨在將進程管理整合進包中。與功能比較都是守護的進程管理器。 什么是CGI CGI全稱是公共網(wǎng)關接口(Common Gateway Interface),HTTP服務器與你的或其它機器上的程序進行交談的一種工具,其程序須運行在網(wǎng)絡服務器上。 CGI可以用任何一種語言編...
摘要:介紹每有一個用戶請求,都會先要創(chuàng)建的子進程,然后處理請求,處理完后結束這個子進程,這就是模式。當子進程關閉連接時,請求便告處理完成。子進程接著等待并處理來自進程管理器的下一個連接。運行在模式時,提供的方法。 本文介紹,PHP運行在FastCGI模式時,F(xiàn)PM提供的方法:fastcgi_finish_request。 在說這個方法之前,我們先了解PHP有哪些常用的運行模式? PHP運行模...
閱讀 2081·2023-04-25 17:57
閱讀 1287·2021-11-24 09:39
閱讀 2487·2019-08-29 16:39
閱讀 3317·2019-08-29 13:44
閱讀 3126·2019-08-29 13:14
閱讀 2323·2019-08-26 11:36
閱讀 3815·2019-08-26 11:00
閱讀 952·2019-08-26 10:14