免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 7159 | 回复: 19
打印 上一主题 下一主题

Fast CGI 工作原理 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-18 11:49 |只看该作者 |正序浏览
标准在哪里呀?
网找的文章都是说它怎么怎么好.具体的都不讲.

我想知道,假如我用纯C语言怎么样才能写出符合FastCGI标准的程序?
如果FastCGI在http服务器中以进程池方式实现,那么服务器是怎么样与子进程通信来分派新的request任务?

论坛徽章:
0
20 [报告]
发表于 2009-11-28 08:00 |只看该作者
对于web的服务器端程序的,有两种方式:

1.使用只有一个入口,其他都是模块。通过在get或者post命令中加入其他变量识别,例如method=login,  method=register,
2.是采用多个分立的程序login.cgi或者register.cgi。

对于普通的cgi来说,这种单入口方式并没有什么好处,因为每次都要编译一次,但只执行一小部分,然后从内存中清掉,效率会低一些。
但对于fastcgi来说,就不一样了。fastcgi设计上就是单入口,即使你在页面中使用的不同的脚本名,例如login.cgi或者register.cgi,最后还是从dispatch.cgi这个唯一的入口进入,当然脚本名称可以从环境变量中分辨出来。

既然fastcgi设计中就是单入口,那么何不在你的cgi脚本中配合,也使用单入口呢? dispatch.cgi是驻留内存的,所有的脚本只需要编译一次。
你的html无需修改,如果是使用login.cgi和register.cgi,那么你可以在环境变量SCRIPT_NAME识别,然后调用不同的子程序即可。

在fastcgi下,使用单个分立的程序没有任何好处。每次都去eval一个程序,都需要重新编译一次,效率很低。另外fastcgi最大的优势是可以共享变量,特别是db的handle。你那么多分立的程序去共享变量,不觉得很怪异吗?

论坛徽章:
0
19 [报告]
发表于 2009-11-27 11:01 |只看该作者

回复 #18 billypeng 的帖子

谢谢 billypeng 的回复.但还是有些地方不是很明白.本人比较笨,别见怪
按你说所说的,我上面给出的那个 dispatch.fcgi 处理的应该是把普通的cgi加载到内存,dispatch.fcgi本身只负责分发请求.但是你上面的 dispatch 脚本好像直接就是一个 web 页面程序.也就是所有 fastcgi 请求都由你的 dispatch 脚本处理完了.但是这样就很奇怪了,难道你的web服务器只有一个 fastcgi 页面?
这个 dispatch 脚本处理 socket 过来的请求这个没错吧?如果需要把这些请求分发到不同的 fcgi 脚本去处理(例如 test1.fcgi,test2,fcgi),那么实际上每次请求不也需要重新编译运行一下那个对应的 test fcgi 脚本吗?

论坛徽章:
0
18 [报告]
发表于 2009-11-20 21:13 |只看该作者

回复 #17 hotsnow 的帖子

1.你这个dispatch实现的是把原来的cgi程序直接搬过来,看起来具有一定的通用性,但fastcgi可以完全不用这种方式。
2.我的dispatch通常是这样写的。

  1. #!/usr/bin/perl
  2. use CGI;
  3. use CGI::Fast qw(:standard);
  4. use CGI::Carp qw(fatalsToBrowser);

  5. while(my $cgi = new CGI::Fast)
  6. {
  7.         $url    = $cgi->self_url(-rewrite=>0, -query=>0);
  8.          if($url =~ /$filename/)
  9.          {
  10.               /* do something */
  11.          }
  12. }
复制代码


可见只是结构相似而言,你列的这种方式,使用cache来缓存cgi脚本,提高了加载速度,但每次还得解释器翻译。我使用的方式在加载时就加载到内存中了,而且只要编译一次,执行效率更高一些。

论坛徽章:
0
17 [报告]
发表于 2009-11-20 13:26 |只看该作者
原帖由 billypeng 于 2009-11-19 09:26 发表
1. 其他程序启动,就是指通过spawn-fcgi启动。
2.dispatch.fcgi就是你自己写的daemon程序,也就是那个死循环的程序,它可以由lighttpd启动或者spawn-fcgi启动,这个就是你自己的fastcgi的脚本,没有另外的脚本了。


谢谢回答.
不过这里我觉得 dispatch.fcgi 不是我自己的fastcgi 脚本.这个应该是处理fastcgi服务和自己的fastcgi脚本通信的把?看看这个 lighty 的配置文件
  1. fastcgi.server    = ( ".fcgi" =>
  2.     ((  
  3.         "socket" => "/path/to/fastcgi.socket",
  4.         "bin-path" => "/path/to/dispatch.fcgi",
  5.     ))  
  6. )
复制代码

  1. $ cat dispatch.fcgi
  2. #!/usr/bin/perl

  3. use strict;
  4. use CGI::Fast;
  5. use Embed::Persistent;

  6. {
  7.     my $p = Embed::Persistent->new();
  8.     while (new CGI::Fast) {
  9.         my $filename = $ENV{SCRIPT_FILENAME};

  10.         my $package = $p->valid_package_name($filename);
  11.         my $mtime;
  12.         if ($p->cached($filename, $package, \$mtime))
  13.         {   
  14.             eval {$package->handler;};
  15.         }   
  16.         else
  17.         {   
  18.             $p->eval_file($ENV{SCRIPT_FILENAME});
  19.         }   
  20.     }   
  21. }
复制代码


刚开始学习 fastcgi,请多多指教.

论坛徽章:
0
16 [报告]
发表于 2009-11-19 13:02 |只看该作者
你说得对,在fastcgi方式处理部分,httpserver相当于一个hub了。

论坛徽章:
0
15 [报告]
发表于 2009-11-19 12:18 |只看该作者
CGI 用重定向与httpserver通讯,FastCGI用Socket直接处理Browser的原始信息?
如何做的好的话,是不是FastCGI程序相当于一个独立的httpserver?

[ 本帖最后由 rrrrrrrr8 于 2009-11-19 12:31 编辑 ]

论坛徽章:
0
14 [报告]
发表于 2009-11-19 12:12 |只看该作者
在fastcgi下,那些环境变量仍然有效。不过你如果不使用外面提供的库来写fastcgi程序,那么就得你自己从tcp/ip连接中读数据并分析。
在perl的fastcgi实现中,FCGI和CGI::Fast 模块,就做好了这件事。

C的例子如下:

  1.     #include "fcgi_stdio.h"
  2.     #include <stdlib.h>

  3.     void main(void)
  4.     {
  5.         int count = 0;
  6.         while(FCGI_Accept() >= 0)
  7.             printf("Content-type: text/html\r\n"
  8.                    "\r\n"

  9.                    "<title>FastCGI Hello!</title>"
  10.                    "<h1>FastCGI Hello!</h1>"
  11.                    "Request number %d running on host <i>%s</i>\n",
  12.                     ++count, getenv("SERVER_NAME"));
  13.     }


复制代码

论坛徽章:
0
13 [报告]
发表于 2009-11-19 11:52 |只看该作者
fastcgi的标准文档:http://www.fastcgi.com  这些文档10多年没有修改过了。说明人家制订规范的时候考虑得非常周全。不象某些国家,宪法,法律当做儿戏,想改就改。
httpserver通过TCP/IP和fastcgi连接,前面已经说了fastcgi程序侦听了一个端口,httpserver连接那个端口。(fastcgi程序的ip地址和端口都在配置中指定)。

2.httpserver直接连接fastcgi侦听的端口,这样就得到了一个fastcgi进程来处理。
3.httpserver没有规定要知道fastcgi程序是否空闲,因为那个侦听地址和端口是重用的,每个fastcgi进程都可以accept连接,如果哪个空闲,说明它处于accept处,会接收连接。否则httpserver连接不上。
4.输入和输出都是通过这个tcp/ip连接做啦,然后再由httpserver发送到浏览器。

如果是httpserver启动fastcgi程序,那么作为父进程肯定知道子进程的的个数,也可以控制,如果老是连接不上,就说明忙,多启动几个。
如果是通过spawn-cgi启动,httpserver完全无法知道有多少个fastcgi程序在提供服务。

论坛徽章:
0
12 [报告]
发表于 2009-11-19 10:43 |只看该作者
thanks billypeng,

我知道CGI工作原理是,HttpServer把request头信息加到子进程的环境变量,把body写到子进程stdin.读出stdout写给browser.就这么简单. 标准文档在 http://www.ietf.org/rfc/rfc3875 .

那么fastcgi标准文档是哪里呀?
跟据billypeng解答,我还有一些疑问:
HttpServer如何与一个FastCGI程序协同工作?
1 从HttpServer得到一个request开始.
2 如何得到一个FastCGI进程?
3 如何知道FastCGI进程处于空闲?
4 如何传递Request给FastCGI进程?
4 如何获取FastCGI输出?
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP