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