摘要:原文开发之介绍和环境搭建由于需要做一些简单的基于的开发,开始学习和调研,本篇介绍和的概念以及基于官方的,以及搭建起简单的开发环境,以作备忘。所以程序其实没有语言限制,只要能够读取环境变量,读写标准输入输出即可。管理器有多种形式。
原文:FastCGI+lighttpd开发之介绍和环境搭建
由于需要做一些简单的基于FastCGI的Web开发,开始学习和调研,本篇介绍CGI和FastCGI的概念以及基于FastCGI官方的devkit,以及lighttpd搭建起简单的开发环境,以作备忘。
为啥要搞这个?现在开发Web有N种选择,啥php,C#,java,ruby,nodejs...哪个都比开发FastCGI要简单和强大的多,为何还要跑到这么个底层来做Web服务呢?答案是嵌入式系统需求!我们知道嵌入式系统往往由于硬件的限制,为了节约处理器和内存,很多事情都需要省的点用。对于简单的Web服务,没有必要(或者不能)去使用高层次的编程框架,那么这个时候,就可以直接基于CGI那套协议来进行开发。通常在这个层次下,C语言是首选。
FastCGI和CGI的概念要搞清楚FastCGI,必须先搞清楚CGI
参考
CGI与FastCGI
Nginx + CGI/FastCGI + C/Cpp
搞不清FastCgi与PHP-fpm之间是个什么样的关系
CGICGI是一种协议,用于扩展Web服务器原本的能力。我们知道,Web服务器最早是用来提供静态文件访问的,想要实现动态内容提供是比较困难的。CGI因此而产生。这是一套协议,简单的说,就是Web服务器在必要的时候,为了处理Request,会调起一个进程(CGI程序),让这个进程来处理请求,并将这个进程返回的结果返回给客户端。然后进程结束,下次请求重复这个过程。这个过程中涉及到Web进程和CGI程序进程的输入和输出协议,这个机制和协议就叫CGI。那么具体的说,在CGI程序中,输入和输出是通过stdin,stdout,stderr来进行的,请求的参数等则是通过环境变量来传递的。所以CGI程序其实没有语言限制,只要能够读取环境变量,读写标准输入输出即可。下图以Apache和Python为例,说明CGI的工作方式
Python的CGI扩展能够在Python解释器的帮助下,解释用户编写的Python脚本,从而输入输出,虽然这个模型相比上面阐述的基本模型要复杂一点,但是本质是相同的。
CGI的缺点很明显,每个请求都要启动进程来处理请求,进程启动的开销是没有必要的。
FastCGI为了解决CGI的缺点,诞生了FastCGI。既然CGI的缺点是进程的频繁启动和关闭,那么是否可以有一个专门管理CGI进程的程序,在没有Request请求的情况下,保持多个CGI进程的挂起状态,当有请求的时候,分配一个进程来处理,处理完成后挂起,就像是进程池一样。这个进程池的管理程序称为FastCGI管理器,从字面看,它可以提高CGI程序的效率。
不光是处理模型的优化,CGI程序只能在Web服务器本机执行,而基于FastCGI的管理下,CGI程序可以被部署在远程,通过TCP Socket或者Unix domain Socket来传输数据,这种模式可以理解为FastCGI代理。
FastCGI管理器有多种形式。例如:Apache和Lighttpd是通过模块的方式实现FastCGI管理器的,而Nginx则是通过FastCGI代理模式实现的(也就是说需要一个多带带的FastCGI管理器进程,该进程通过侦听TCP Socket或者Unix domain Socket在Nginx和CGI程序之间起到桥梁作用)。
同样是Apache和Python为例,下图为FastCGI的启动和运行的模型
Apache在调用用户脚本的时候,会依靠Apache内建的FastCGI模块来调度CGI进程,CGI进程也不会消亡,下次请求就不需要重新启动解析器了。而且CGI进程是通过Socket形式实现输入输出的,当然CGI程序在编写的时候,仍然是通过stdin,stdout,stderr来输入输出,只是最终可能是通过网络来实现的,这样做可以实现从CGI程序到FastCGI程序的平滑过渡。你会发现开发FastCGI程序跟开发CGI程序并没有多少区别。
关于Nginx的FastCGI代理模式,有必要多说几句。Nginx自身没有实现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,那么还需要一个程序来监听127.0.0.1:9000啊,对了!这个程序就是php-fpm,所以我们在用Nginx配置php的时候需要:
php-fpm start
php-fpm可以帮Nginx实现CGI进程管理器的功能。看起来好麻烦有没有,为什么Apache无需php-fpm,原因上面说了,Apache是通过模块实现的,无需多带带启动php-fpm。
那么,如何开始开发一个FastCGI程序呢,我们需要FastCGI的开发套件,以及一个合适的Web服务器,这里FastCGI套件从这里下载,Web服务器,我们选择了lighttpd,因为既然要直接开发CGI程序,那么通常你会选择尽可能轻量的Web服务器。当然支持FastCGI的Web服务器很多,这里有列表。
准备lighttpdlighttpd的安装就不多说了,你可以选择编译安装或者源安装,我选择了编译安装,所以后续的启动啥的麻烦一点。
lighttpd的启动和重启如果是编译安装的,那么你需要将源码包doc里面的config文件夹复制到/etc下,并重命名为lighttpd,这里面是lighttpd的一系列启动配置,然后像下面这样启动:
/usr/local/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf
如果你经常折腾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个(对于嵌入式系统,并不是要处理高并发,多个进程并没有意义)
我们可以通过浏览器访问http://localhost/cgi-bin/fh.fcgi,即可执行fh.fcgi程序(这里htdocs是配置的文档根目录)。
那么接下来的重点是开发/htdocs/cgi-bin/fh.fcgi程序。
开始开发FastCGI程序 开发套件的安装下载好套件后,解压在fcgi-devel-kit目录
cd fcgi-devel-kit ./configure make cd libfcgi make make install
显然我们其实需要的是FastCGI的include和lib,上面的命令可以在/usr/local/lib下创建几个相关的库文件:
-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是静态库,.la是基于libtool的链接库。后面你可以选择使用.a来链接,也可以使用libtool工具,使用.la来构建。
完成套件的安装后,先创建一个项目文件,并将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
创建一个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程序的关键区别在于while(FCGI_Accept() >= 0),这个条件会在没有请求需要处理的时候阻塞,那么进程就会挂起,并在正常情况下不会退出。这样就实现了进程驻留的效果。
编译和链接使用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,前者用于继续用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链接后生成的(动态链接),可以看到libtool实际上只是对gcc的一个包装而已。据说是为了方便解决依赖库,笔者折腾了好久才弄清楚。
最后,将fh复制到目标目录,并重命名。当然如果fh.fcgi进程已经由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的开发,后续还需要使用IDE来开发,并实现交叉编译,后面再折腾了。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/21223.html
摘要:当客户端请求到达时,进程管理器选择并连接到一个解释器。什么是是一个管理器,是只用于的可以在下载得到其实是源代码的一个补丁,旨在将进程管理整合进包中。与功能比较都是守护的进程管理器。 什么是CGI CGI全称是公共网关接口(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行交谈的一种工具,其程序须运行在网络服务器上。 CGI可以用任何一种语言编...
摘要:介绍每有一个用户请求,都会先要创建的子进程,然后处理请求,处理完后结束这个子进程,这就是模式。当子进程关闭连接时,请求便告处理完成。子进程接着等待并处理来自进程管理器的下一个连接。运行在模式时,提供的方法。 本文介绍,PHP运行在FastCGI模式时,FPM提供的方法:fastcgi_finish_request。 在说这个方法之前,我们先了解PHP有哪些常用的运行模式? PHP运行模...
阅读 2048·2023-04-25 17:57
阅读 1270·2021-11-24 09:39
阅读 2456·2019-08-29 16:39
阅读 3294·2019-08-29 13:44
阅读 3052·2019-08-29 13:14
阅读 2285·2019-08-26 11:36
阅读 3762·2019-08-26 11:00
阅读 929·2019-08-26 10:14