网关协议学习:CGI、FastCGI、WSGI

CGI 程序(user.c)

#include <stdio.h>
#include <stdlib.h>
// 通过获取的 id 查询用户的信息
int main(void){

    //============================ 模拟数据库 ============================
    typedef struct 
    {
        int  id;
        char *username;
        int  age;
    } user;

    user users[] = {
        {},
        {
            1,
            "mengkang.zhou",
            18
        }
    };
    //============================ 模拟数据库 ============================

    char *query_string;
    int id;

    query_string = getenv("QUERY_STRING");

    if (query_string == NULL)
    {
        printf("没有输入数据");
    } else if (sscanf(query_string,"id=%d",&id) != 1)
    {
        printf("没有输入id");
    } else
    {
        printf("用户信息查询<br>学号: %d<br>姓名: %s<br>年龄: %d",id,users[id].username,users[id].age);
    }

    return 0;
}

将方面包车型大巴 CGI
程序编写翻译成gcc user.c -o user.cgi,放在上边web程序的同级目录。

代码中的第28行,从境况变量中读取前面在Web服务器守护进度中安装的情状变量,是大家演示的主要。

  1. 打破古板页面管理才干。守旧的页面处理技术,程序必需与 Web 服务器或
    Application
    服务器处于相仿台服务器中。这种历史已经早N年被FastCGI技能所打破,法斯特CGI本领的应用程序能够被设置在服务器群中的任何大器晚成台服务器,而由此TCP/IP 共同商议与 Web 服务器通信,这样做既切合开辟大型分布式 Web
    群,也合乎高效数据库调控。
  2. 明显的伸肢人体模型特式。CGI 技能还未有二个总来说之的剧中人物,在 法斯特CGI
    程序中,程序被赋予分明的剧中人物(响应器剧中人物、认证器剧中人物、过滤器角色)。

FastCGI简介

CGI一触即发是“通用网关接口”(Common
Gateway Interface卡塔尔,
它能够让几个顾客端,从网页浏览器向实行在Web服务器上的顺序央浼数据。
CGI描述了客商端和那一个程序之间传输数据的大器晚成种规范。
CGI的八个目标是要独自于别的语言的,所以CGI能够用别样生机勃勃种语言编写,只要这种语言具备标准输入、输出和情形变量。如php,perl,tcl等

FastCGI疑似二个常驻(long-live卡塔尔型的CGI,
它能够直接试行着,只要激活后,不会每一次都要花销时间去fork一次(那是CGI最为人诟病的fork-and-execute
情势卡塔尔。 它还扶植遍及式的演算, 即 法斯特CGI
程序能够在网址服务器以外的主机上试行何况选取来自别的网址服务器来的伸手。

法斯特CGI是语言非亲非故的、可伸缩结构的CGI开放扩充,其利害攸关表现是将CGI解释器进程保持在内部存款和储蓄器中并据此拿到较高的属性。
大名鼎鼎,CGI解释器的频频加载是CGI品质低下的关键原因,假如CGI解释器保持在内部存款和储蓄器中并收受法斯特CGI进度管理器调解,
则可以提供卓越的习性、伸缩性、Fail- Over个性等等。

相似景观下,法斯特CGI的全部办事流程是这么的。

  1. Web Server运行时载入法斯特CGI进度微机(IIS ISAPI或Apache ModuleState of Qatar
  2. 法斯特CGI进度管理器自己早先化,运转七个CGI解释器进度(可以知道四个php-cgi卡塔尔并伺机来自Web
    Server的接连。
  3. 当客户端央浼到达Web
    Server时,法斯特CGI进度管理器选取并接连到二个CGI解释器。Web
    server将CGI意况变量和职业输入发送到法斯特CGI子进度php-cgi。
  4. 法斯特CGI子进度完毕处理后将正式输出和错误音讯从同三番五次接重临Web
    Server。当FastCGI子进程关闭连接时,央求便告管理到位。法斯特CGI子进程接着等待并拍卖来自FastCGI进度微处理机(运维在Web
    Server中卡塔尔的下一个一而再接二连三。 在CGI情势中,php-cgi在那便脱离了。

有备无患专门的工作

大概上边的剧情精通起来依然很肤浅,那是出于第风度翩翩对法斯特CGI公约还尚无三个光景的认知,第二并未有实际代码的学习。所以供给事情未发生前学习下
法斯特CGI
左券的开始和结果,不料定要求完全看懂,可差不离明白之后,看完本篇再结合着学习了然消化吸取。

http://www.fastcgi.com/devkit… (România语原版)
http://andylin02.iteye.com/bl… (中文版)

  1. 只管fork进程,子进程挂了,主进程仅仅log记录叁次,根本不会再度fork。在二〇一〇年生龙活虎段时间内,作者早就用spawn-fcgi安插php-cgi,当跑后生可畏段时间就能够全挂掉,只好用crontab定时重启spawn-fcgi
  2. 不辜负担子进程中的互联网IO,把socket放到钦定地点就完了,接下去的事务由被spawn的程序管理

PHP中的CGI实现

PHP的CGI达成精气神是是以socket编制程序完结三个TCP或UDP左券的服务器,当运营时,创立TCP/UDP左券的服务器的socket监听,
并选用相关诉求举办拍卖。那只是伸手的管理,在这里基本功上加多模块初阶化,sapi初步化,模块关闭,sapi关闭等就重新组合了总体CGI的生命周期。

以TCP为例,在TCP的服务端,日常会履行那样多少个操作步骤:

  1. 调用socket函数成立贰个TCP用的流式套接字;
  2. 调用bind函数将服务器的地头地址与眼下制造的套接字绑定;
  3. 调用listen函数将新创造的套接字作为监听,等待顾客端发起的连接,当客商端有多少个接二连三连接到那个套接字时,可能须要排队管理;
  4. 服务器进程调用accept函数走入窒碍状态,直到有客户进程调用connect函数而创建起五个接连;
  5. 当与顾客端成立连接后,服务器调用read_stream函数读取顾客的乞请;
  6. 拍卖完数据后,服务器调用write函数向客商端发送应答。

TCP上客户-服务器业务的时序如图2.6所示:

奥门新浦京官方网站 1

PHP的CGI实现从cgi_main.c文件的main函数开头,在main函数中调用了定义在fastcgi.c文件中的开头化,监听等函数。
相比较TCP的流程,大家查阅PHP对TCP协议的落实,就算PHP本身也促成了那么些流程,不过在main函数中一些进程被封装成三个函数达成。
对应TCP的操作流程,PHP首先会推行创立socket,绑定套接字,创制监听:

if (bindpath) {
    fcgi_fd = fcgi_listen(bindpath, 128);   //  实现socket监听,调用fcgi_init初始化
    ...
}

在fastcgi.c文件中,fcgi_listen函数重要用以创制、绑定socket并最早监听,它走完了前边所列TCP流程的前四个级次,

    if ((listen_socket = socket(sa.sa.sa_family, SOCK_STREAM, 0)) < 0 ||
        ...
        bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 ||
        listen(listen_socket, backlog) < 0) {
        ...
    }

当服务端伊始化完结后,进度调用accept函数步向拥塞状态,在main函数中大家看出如下代码:

    while (parent) {
        do {
            pid = fork();   //  生成新的子进程
            switch (pid) {
            case 0: //  子进程
                parent = 0;

                /* don't catch our signals */
                sigaction(SIGTERM, &old_term, 0);   //  终止信号
                sigaction(SIGQUIT, &old_quit, 0);   //  终端退出符
                sigaction(SIGINT,  &old_int,  0);   //  终端中断符
                break;
                ...
                default:
                /* Fine */
                running++;
                break;
        } while (parent && (running < children));

    ...
        while (!fastcgi || fcgi_accept_request(&request) >= 0) {
        SG(server_context) = (void *) &request;
        init_request_info(TSRMLS_C);
        CG(interactive) = 0;
                    ...
            }

如上的代码是二个生成子进程,并等待客商央求。在fcgi_accept_request函数中,程序会调用accept函数窒碍新创立的历程。
当顾客的呼吁到达时,fcgi_accept_request函数会判定是或不是处理客户的呼吁,在那之中会过滤某个连接央浼,忽视受节制顾客的央求,
假设程序受理顾客的恳求,它将剖析乞求的新闻,将相关的变量写到对应的变量中。
当中在读取央浼内容时调用了safe_read方法。如下所示: [main() ->
fcgi_accept_request() -> fcgi_read_request() ->
safe_read()]

static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count)
{
    size_t n = 0;
    do {
    ... //  省略  对win32的处理
        ret = read(req->fd, ((char*)buf)+n, count-n);   //  非win版本的读操作
    ... //  省略
    } while (n != count);

}

如上相应服务器端读取客商的伸手数据。

在号召伊始化达成,读取乞求达成后,就该管理央求的PHP文件了。
要是此番诉求为PHP_MODE_STANDAPRADOD则会调用php_execute_script推行PHP文件。
在那函数中它先初叶化此文件有关的后生可畏对剧情,然后再调用zend_execute_scripts函数,对PHP文件进行词法深入分析和语法分析,生成人中学间代码,
并施行zend_execute函数,进而推行那几个中间代码。关于任何脚本的进行请参见第1节脚本的进行。

在拍卖完顾客的伏乞后,服务器端将回到音讯给顾客端,那时在main函数中调用的是fcgi_finish_request(&request,
1); fcgi_finish_request函数定义在fastcgi.c文件中,其代码如下:

int fcgi_finish_request(fcgi_request *req, int force_close)
{
int ret = 1;

if (req->fd >= 0) {
    if (!req->closed) {
        ret = fcgi_flush(req, 1);
        req->closed = 1;
    }
    fcgi_close(req, force_close, 1);
}
return ret;
}

如上,当socket处于打开状态,而且号令未关门,则会将推行后的结果刷到顾客端,并将号令的关闭设置为真。
将数据刷到客商端的次序调用的是fcgi_flush函数。在那函数中,关键是在意答应头的结构和写操作。
程序的写操作是调用的safe_write函数,而safe_write函数中对此最终的写操作针对win和linux景况做了分别,
在Win32下,假诺是TCP连接则用send函数,假若是非TCP则和非win碰着大器晚成招致用write函数。如下代码:

#ifdef _WIN32
if (!req->tcp) {
    ret = write(req->fd, ((char*)buf)+n, count-n);
} else {
    ret = send(req->fd, ((char*)buf)+n, count-n, 0);
    if (ret <= 0) {
            errno = WSAGetLastError();
    }
}
#else
ret = write(req->fd, ((char*)buf)+n, count-n);
#endif

在殡葬了需要的应对后,服务器端将会实行关闭操作,只限于CGI自身的倒闭,程序实施的是fcgi_close函数。
fcgi_close函数在前边提的fcgi_finish_request函数中,在伸手应答完后进行。相仿,对于win平台和非win平台有两样的管理。
此中对于非win平台调用的是write函数。

以上是二个TCP服务器端实现的简洁明了表达。那只是我们PHP的CGI方式的根基,在此个基本功上PHP增添了更加多的功力。
在前边的章节中大家关系了各类SAPI都有五个直归于它们本人的sapi_module_struct结构:cgi_sapi_module,其代码定义如下:

/* {{{ sapi_module_struct cgi_sapi_module
 */
static sapi_module_struct cgi_sapi_module = {
"cgi-fcgi",                     /* name */
"CGI/FastCGI",                  /* pretty name */

php_cgi_startup,                /* startup */
php_module_shutdown_wrapper,    /* shutdown */

sapi_cgi_activate,              /* activate */
sapi_cgi_deactivate,            /* deactivate */

sapi_cgibin_ub_write,           /* unbuffered write */
sapi_cgibin_flush,              /* flush */
NULL,                           /* get uid */
sapi_cgibin_getenv,             /* getenv */

php_error,                      /* error handler */

NULL,                           /* header handler */
sapi_cgi_send_headers,          /* send headers handler */
NULL,                           /* send header handler */

sapi_cgi_read_post,             /* read POST data */
sapi_cgi_read_cookies,          /* read Cookies */

sapi_cgi_register_variables,    /* register server variables */
sapi_cgi_log_message,           /* Log message */
NULL,                           /* Get request time */
NULL,                           /* Child terminate */

STANDARD_SAPI_MODULE_PROPERTIES
};
/* }}} */

同后生可畏,以读取cookie为例,当我们在CGI意况下,在PHP中调用读取Cookie时,
最后得到的数额的岗位是在激活SAPI时。它所调用的诀要是read_cookies。

SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);

对于每三个服务器在加载时,大家都钦点了sapi_module,在首先小节的Apache模块方式中,
sapi_module是apache2_sapi_module,其对应read_cookies方法的是php_apache_sapi_read_cookies函数,
而在我们那边,读取cookie的函数是sapi_cgi_read_cookies。
再一次注解定义SAPI布局的说辞:统意气风发接口,面向接口的编制程序,具备更加好的增加性和适应性。

6.施行脚本

假诺这次哀求为PHP_MODE_STANDARD则会调用php_execute_script试行PHP文件。这里就不开展了。

CGI

参照他事他说加以考察资料

这是TIPI项目其次章第三小节修正后的版本内容,即便还应该有部分难点,不过较在此以前的本子照旧具备进步,
起码大家在使劲…

正文地址:PHP的CGI实现    作品出处:PHP源码阅读,PHP设计方式,PHP学习笔记,项目管理-胖胖的空中

转发请以链接方式注解原始出处和我,谢绝不尊重版权者抄袭!

FCGI_BEGIN_REQUEST 的定义

typedef struct _fcgi_begin_request {
    unsigned char roleB1;
    unsigned char roleB0;
    unsigned char flags;
    unsigned char reserved[5];
} fcgi_begin_request;

字段解释

role意味着Web服务器期待利用扮演的角色。分为四个剧中人物(而大家那边研究的境况日常都是响应器脚色)

typedef enum _fcgi_role {
    FCGI_RESPONDER    = 1,
    FCGI_AUTHORIZER    = 2,
    FCGI_FILTER        = 3
} fcgi_role;

FCGI_BEGIN_REQUEST奥门新浦京官方网站,中的flags零零部件包罗三个操纵线路关闭的位:flags & FCGI_KEEP_CONN:固然为0,则使用在对此番诉求响应后关门线路。若是非0,应用在对此番诉求响应后不会停业线路;Web服务器为线路保持响应性。

CGI格局在遇见三番五次央浼(客商央浼)先要创造cgi的子进度,激活八个CGI进度,然后管理央浼,管理完后竣事这几个子进程。那正是fork-and-execute方式。所以用cgi情势的服务器有多少连接央求就能有稍许cgi子进度,子进度每每加载是cgi质量低下的重大缘由。当顾客供给数量超级多时,会大批量占用系统的能源如内部存款和储蓄器,CPU时间等,产生机能低下。

法斯特CGI 新闻类型

法斯特CGI 将传输的新闻做了广大品种的分割,其布局体定义如下:

typedef enum _fcgi_request_type {
    FCGI_BEGIN_REQUEST      =  1, /* [in]                              */
    FCGI_ABORT_REQUEST      =  2, /* [in]  (not supported)             */
    FCGI_END_REQUEST        =  3, /* [out]                             */
    FCGI_PARAMS             =  4, /* [in]  environment variables       */
    FCGI_STDIN              =  5, /* [in]  post data                   */
    FCGI_STDOUT             =  6, /* [out] response                    */
    FCGI_STDERR             =  7, /* [out] errors                      */
    FCGI_DATA               =  8, /* [in]  filter data (not supported) */
    FCGI_GET_VALUES         =  9, /* [in]                              */
    FCGI_GET_VALUES_RESULT  = 10  /* [out]                             */
} fcgi_request_type;

uWSGI
项目目的在于为布局遍布式集群的互联网利用开辟朝气蓬勃套完整的缓慢解决方案。uWSGI主要面向web及其标准服务,已经打响的选拔于多样不一致的语言。由于uWSGI的可扩展构造,它亦可被无界定的扩大用来支撑越多的阳台和语言。近些日子,你能够使用C,C++和Objective-C来编排插件。项目名称中的“WSGI”是为着向同名的Python
Web规范表示多谢,因为WSGI为该类型支出了第三个插件。uWSGI是一个Web服务器,它达成了WSGI公约、uwsgi、http等合计。uWSGI,既不用wsgi契约也不用法斯特CGI公约,而是自创了一个uwsgi的议和,uwsgi商业事务是叁个uWSGI服务器自有的商量,它用来定义传输音讯的项目(type
of information),每二个uwsgi
packet前4byte为传输音讯项目描述,它与WSGI相比较是两样东西。传说该左券差不离是fcgi左券的10倍那么快。

7.了事央求

fcgi_finish_request(&request, 1);

int fcgi_finish_request(fcgi_request *req, int force_close)
{
    int ret = 1;

    if (req->fd >= 0) {
        if (!req->closed) {
            ret = fcgi_flush(req, 1);
            req->closed = 1;
        }
        fcgi_close(req, force_close, 1);
    }
    return ret;
}

fcgi_finish_request中调用fcgi_flushfcgi_flush中封装叁个FCGI_END_REQUEST消息体,再通过safe_write写入
socket 连接的客商端描述符。

奥门新浦京官方网站 2

音讯的出殡顺序

下图是叁个简练的信息传递流程

奥门新浦京官方网站 3

最首发送的是FCGI_BEGIN_REQUEST,然后是FCGI_PARAMSFCGI_STDIN,由于种种音信头(下边将详细表明)里面能够继承的最大尺寸是65535,所以这两种类型的音信不自然只发送叁遍,有希望总是发送多次。

FastCGI
响应体管理达成之后,将发送FCGI_STDOUTFCGI_STDERR,同理也说不许数次三翻五次发送。最终以FCGI_END_REQUEST代表哀告的利落。

急需专一的少数,FCGI_BEGIN_REQUESTFCGI_END_REQUEST各自标识着伸手的开首和告竣,与成套公约生死相依,所以他们的音讯体的剧情也是探究的生机勃勃部分,由此也许有对应的构造体与之对应(前边会详细表达)。而境况变量、规范输入、规范输出、错误输出,那几个都以事情相关,与商业事务非亲非故,所以她们的消息体的内容则无布局体对应。

由于一切音讯是二进制延续传递的,所以必需定义八个统风姿洒脱的组织的音信头,这样以便读取每一种新闻的音信体,方便音讯的切割。那在网络通信中是极度布满的意气风发种手腕。

法斯特CGI是从CGI发展更上意气风发层楼而来的。古板CGI接口情势的重大劣点是性质非常差,因为每一遍HTTP服务器蒙受动态程序时都亟需重新起动脚本解析器来实施深入分析,然后结果被重临给HTTP服务器。那在管理高并发访问时,差相当的少是不可用的。法斯特CGI疑似贰个常驻(long-liveState of Qatar型的CGI,它可以直接实行着,只要激活后,不会每一回都要花销时间去fork壹回(那是CGI最为人诟病的fork-and-execute
情势卡塔尔。CGI 就是所谓的短生存期应用程序,法斯特CGI
正是所谓的长生存期应用程序。由于 法斯特CGI
程序并无需不断的发出新历程,能够大大裁减服务器的压力况且发生较高的行使成效。它的快慢效能起码要比CGI
技艺进步 5 倍以上。它还支持分布式的运算, 即 法斯特CGI
程序能够在网址服务器以外的主机上试行况且接收来自其他网址服务器来的伸手。

法斯特CGI 专业原理剖判

对峙于 CGI/1.1 标准在 Web 服务器在地面 fork 三个子进度实施 CGI
程序,填充 CGI 预约义的环境变量,放入系统意况变量,把 HTTP body 体的
content 通过专门的事业输入传入子进度,管理完成之后通过正规输出再次来到给 Web
服务器。法斯特CGI 的着力则是不允许古板的 fork-and-execute
情势,减少每一遍运行的有才能的人费用(后边以 PHP
为例表达),以常驻的章程来拍卖要求。

法斯特CGI 专业流程如下:

  1. 法斯特CGI 进程微处理器本人先河化,运维八个 CGI 解释器进程,并听候来自
    Web Server 的总是。
  2. Web 服务器与 法斯特CGI 进程微型机举办 Socket 通讯,通过 法斯特CGI
    合计算与发放送 CGI 境遇变量和专门的学业输入数据给 CGI 解释器进度。
  3. CGI 解释器进程达成管理后将标准输出和错误音讯从同一而再连续接重返 Web
    Server。
  4. CGI 解释器进度接着等待并拍卖来自 Web Server 的下叁个总是。

奥门新浦京官方网站 4

法斯特CGI 与理念 CGI 方式的区分之一则是 Web 服务器不是平昔实践 CGI
程序了,而是通过 socket 与 法斯特CGI 响应器(法斯特CGI
进程微机)举行互相,Web 服务器需求将 CGI 接口数据封装在安分守己 法斯特CGI
公约包中发送给 法斯特CGI 响应器程序。就是出于 法斯特CGI 进度微型机是基于
socket 通讯的,所以也是分布式的,Web服务器和CGI响应器服务器分开陈设。

再啰嗦一句,法斯特CGI
是后生可畏种公约,它是创建在CGI/1.1功底之上的,把CGI/1.1里边的要传递的数额通过法斯特CGI公约定义的逐个、格式举办传递。

很醒目,Spawn-FCGI也是 pre-fork 模型,只是用了上古C语言编写,充满了N多
unix下青古铜色编制程序本领。

FCGI_END_REQUEST 的定义

typedef struct _fcgi_end_request {
    unsigned char appStatusB3;
    unsigned char appStatusB2;
    unsigned char appStatusB1;
    unsigned char appStatusB0;
    unsigned char protocolStatus;
    unsigned char reserved[3];
} fcgi_end_request;

字段解释

appStatus构件是使用级其余状态码。
protocolStatus组件是协商级其他状态码;protocolStatus的值只怕是:

FCGI_REQUEST_COMPLETE:央求的健康甘休。
FCGI_CANT_MPX_CONN:屏绝新央浼。那产生在Web服务器通过一条路径向利用发送并发的伏乞时,前面一个被设计为每条线路每趟管理二个倡议。
FCGI_OVEENCORELOADED:拒却新诉求。这产生在应用用完某个能源时,比方数据库连接。
FCGI_UNKNOWN_ROLE:谢绝新央浼。那发生在Web服务器内定了二个应用不能够分辨的剧中人物时。

protocolStatus在 PHP 中的定义如下

typedef enum _fcgi_protocol_status {
    FCGI_REQUEST_COMPLETE    = 0,
    FCGI_CANT_MPX_CONN        = 1,
    FCGI_OVERLOADED            = 2,
    FCGI_UNKNOWN_ROLE        = 3
} dcgi_protocol_status;

亟需静心dcgi_protocol_statusfcgi_role梯次要素的值都以 法斯特CGI
合同里定义好的,而非 PHP 自定义的。

仿照效法资料:

PHP 中的 FastCGI 的实现

下直面代码的解读笔记只是本身个人文化的三个梳理提炼,如有核对,请我们提议。对目生该代码的校友来讲或者是八个教导,初步认知,假设感到很模糊不清晰,那么照旧须求本人逐行去读书。

php-src/sapi/cgi/cgi_main.c为例实行解析表明,假若开采条件为 unix
境况。main 函数中部分变量的定义,以至 sapi
的发轫化,大家就不研商在那间研商了,只表明有关 法斯特CGI 相关的源委。

PHP-CGI

如上代码中的着重:

  • 66~81行找到CGI程序的相对路线(大家为了不难,直接将其根目录定义为Web程序的当前目录),那样就足以在子进度中奉行CGI 程序了;相同的时候安装情状变量,方便CGI程序运维时读取;
  • 94~95行将 CGI 程序的正规输出结果写入 Web 服务器守护进度的缓存中;
  • 97行则将打包后的 html 结果写入顾客端 socket
    描述符,重返给连接Web服务器的客户端。

ISAPI服务器扩展为利用 Internet 服务器的通用网关接口(CGI卡塔尔(قطر‎应用程序提供了另生机勃勃种选取。与 CGI 应用程序分化,ISA 在
HTTP服务器所在的大同小异域点空间运维,何况能够访谈可由 HTTP
服务器使用的兼具能源。ISA 的类别开采比 CGI
应用程序低,因为它们无需创立别的进度,也不实行须要穿胜进度边界的通讯,而这种通讯极其耗费时间。假设内部存款和储蓄器被别的进程所急需,扩充和挑选器DLL
都或许被卸载。ISAPI 允许在二个 DLL 中有五个指令,这么些命令作为 DLL
中CHttpServer对象的积极分子函数来促成。CGI
必要各样任务有八个独门的名目和叁个到独门的可试行文件的 UENVISIONL
映射。各类新的 CGI
央浼运营叁个新历程,而各种不一致的伏乞包涵在各自的可实行文件中,这一个文件依赖各种供给加载和卸载,由此系统开采高于
ISA。

5.读取数据

上面包车型客车代码删除一些至极意况的拍卖,只呈现了常规情状下举办种种。

fcgi_read_request中则实现我们在音讯电视发表样例中的信息读取,而里面不菲的len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;操作,已经在眼下的法斯特CGI
音讯头中解释过了。

此间是深入分析 法斯特CGI 左券的主要。

static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count)
{
    int    ret;
    size_t n = 0;

    do {
        errno = 0;
        ret = read(req->fd, ((char*)buf)+n, count-n);
        n += ret;
    } while (n != count);
    return n;
}

static int fcgi_read_request(fcgi_request *req)
{
    ...

    if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) {
        return 0;
    }

    len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
    padding = hdr.paddingLength;

    req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0;

    if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) {
        char *val;

        if (safe_read(req, buf, len+padding) != len+padding) {
            return 0;
        }

        req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN);

        switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) {
            case FCGI_RESPONDER:
                val = estrdup("RESPONDER");
                zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
                break;
            ...
            default:
                return 0;
        }

        if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) {
            return 0;
        }

        len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
        padding = hdr.paddingLength;

        while (hdr.type == FCGI_PARAMS && len > 0) {
            if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) {
                req->keep = 0;
                return 0;
            }
            len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
            padding = hdr.paddingLength;
        }

        ...
    }
}
  1. 支撑平滑结束/运营的高等进度管理职能;
  2. 可以干活于区别的 uid/gid/chroot 情形下,并监听分歧的端口和利用分歧的
    php.ini 配置文件(可代替 safe_mode 的设置);
  3. stdout 和 stderr 日志记录;
  4. 在发生意外情形的时候能够重新启航并缓存被破坏的 opcode;
  5. 文本上传优化扶持;
  6. “慢日志” – 记录脚本(不仅仅记录文件名,还记录 PHP backtrace
    音信,能够使用
    ptrace也许相同工具读取和剖判远程进程的运维数据)运行所招致的相当缓慢;
  7. fastcgi_finish_request(State of Qatar –
    特殊功效:用于在伸手完结和刷新数据后,继续在后台实行耗费时间的专门的学问(录入录像调换、计算处理等);
  8. 动态/静态子进程发生;
  9. 主干 SAPI 运市场价格况消息(雷同Apache的 mod_status);
  10. 依据 php.ini 的配置文件。

在商量 法斯特CGI 以前,不能不说守旧的 CGI
的工作规律,同一时间应该大概明白 CGI
1.1 协议

FastCGI 的特点

FastCGI 消息头

如上,法斯特CGI
新闻分10种消息类型,有的是输入过多输出。而具有的新闻都是二个新闻头以前。其结构体定义如下:

typedef struct _fcgi_header {
    unsigned char version;
    unsigned char type;
    unsigned char requestIdB1;
    unsigned char requestIdB0;
    unsigned char contentLengthB1;
    unsigned char contentLengthB0;
    unsigned char paddingLength;
    unsigned char reserved;
} fcgi_header;

字段解释下:

  • version标志法斯特CGI合同版本。
  • type 标志法斯特CGI记录类型,也正是记录实行的貌似意义。
  • requestId标记记录所属的法斯特CGI央浼。
  • contentLength记录的contentData组件的字节数。

至于地点的xxB1xxB0的说道表达:当八个相邻的构造组件除了后缀“B1”和“B0”之外命名相同时,它意味着那三个零器件可正是评估价值为B1<<8
+
B0的单个数字。该单个数字的名字是那些零件减去后缀的名字。这些约定总结了一个由当先三个字节表示的数字的管理方式。

比如说公约头中requestIdcontentLength表示的最大值即是65535

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main()
{
   unsigned char requestIdB1 = UCHAR_MAX;
   unsigned char requestIdB0 = UCHAR_MAX;
   printf("%dn", (requestIdB1 << 8) + requestIdB0); // 65535
}

您大概会想到借使贰个新闻体长度超过65535如何是好,则分割为三个大器晚成律档期的顺序的新闻发送就能够。

任何拓宽文化:Java Servlet、Sinatra、Rack

音信广播发表样例

为了轻松的象征,音讯头只展现新闻的项目和消息的
id,别的字段都不付与呈现。下边包车型大巴例子来自于官方网站

{FCGI_BEGIN_REQUEST,   1, {FCGI_RESPONDER, 0}}
{FCGI_PARAMS,          1, "1302SERVER_PORT801316SERVER_ADDR199.170.183.42 ... "}
{FCGI_STDIN,           1, "quantity=100&item=3047936"}
{FCGI_STDOUT,          1, "Content-type: text/htmlrnrn<html>n<head> ... "}
{FCGI_END_REQUEST,     1, {0, FCGI_REQUEST_COMPLETE}}

协作地点种种架构体,则足以大要想到 FastCGI 响应器的深入分析和响应流程:

先是读取音讯头,获得其品种为FCGI_BEGIN_REQUEST,然后深入剖析其消息体,获知其急需的剧中人物便是FCGI_RESPONDERflag为0,表示央求甘休后关门线路。然后剖判第二段音讯,获知其音讯类型为FCGI_PARAMS,然后径直将消息体里的剧情以回车符切割后存进入国情形变量。与之雷同,管理完毕之后,则赶回了FCGI_STDOUT音信体和FCGI_END_REQUEST音信体供
Web 服务器深入解析。

Web服务器网关接口(Python Web Server Gateway
Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的大器晚成种简易而通用的接口。自从WSGI被开荒出来以往,多数别的语言中也现身了近乎接口。WSGI是作为Web服务器与Web应用程序或利用框架之间的生机勃勃种低等别的接口,以升级可移植Web应用开荒的协同点。WSGI是借助现成的CGI标准而规划的。

8.正经输入标准输出的管理

业内输入和行业内部输出在地方未有同台研商,实际在cgi_sapi_module布局体中有定义,不过cgi_sapi_module这个sapi_module_struct布局体与其他代码耦合太多,作者要好也没深刻的知情,这里大概做下相比较,希望别的网上老铁赋予指导、补充。

cgi_sapi_module中定义了sapi_cgi_read_post来拍卖POST数据的读取.

while (read_bytes < count_bytes) {
    fcgi_request *request = (fcgi_request*) SG(server_context);
    tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
    read_bytes += tmp_read_bytes;
}

fcgi_read中则对FCGI_STDIN的数量开展读取。
同时cgi_sapi_module中定义了sapi_cgibin_ub_write来接管道输送出管理,而个中又调用了sapi_cgibin_single_write,末了实现了FCGI_STDOUT 法斯特CGI
数据包的封装.

fcgi_write(request, FCGI_STDOUT, str, str_length);

法斯特CGI是言语无关的、可伸缩结构的CGI开放扩张,其首要表现是将CGI解释器进程保持在内部存款和储蓄器中并就此赢得较高的性质。驰名中外,CGI解释器的频仍加载是CGI质量低下的要害缘由,倘使CGI解释器保持在内部存款和储蓄器中并选用法斯特CGI进度微处理器调解,则足以提供优良的属性、伸缩性、Fail-Over特性等等。法斯特CGI接口方式接收C/S构造,可以将HTTP服务器和本子深入分析服务器分开,同期在本子拆解深入分析服务器上运转一个如故多个剧本深入分析守护进度。当HTTP服务器每一趟蒙受动态程序时,能够将其直接交付给法斯特CGI进程来实施,然后将拿到的结果回到给浏览器。这种方法能够让HTTP服务器专风流罗曼蒂克地管理静态诉求只怕将动态脚本服务器的结果再次来到给客户端,那在极大程度上抓牢了上上下下应用体系的属性。

4.在子进度中收受伏乞

到这边整个都照旧 socket
的劳动的覆辙。选择乞请,然后调用了fcgi_read_request

fcgi_accept_request(&request)

int fcgi_accept_request(fcgi_request *req)
{
    int listen_socket = req->listen_socket;
    sa_t sa;
    socklen_t len = sizeof(sa);
    req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);

    ...

    if (req->fd >= 0) {
        // 采用多路复用的机制
        struct pollfd fds;
        int ret;

        fds.fd = req->fd;
        fds.events = POLLIN;
        fds.revents = 0;
        do {
            errno = 0;
            ret = poll(&fds, 1, 5000);
        } while (ret < 0 && errno == EINTR);
        if (ret > 0 && (fds.revents & POLLIN)) {
            break;
        }
        // 仅仅是关闭 socket 连接,不清空 req->env
        fcgi_close(req, 1, 0);
    }

    ...

    if (fcgi_read_request(req)) {
        return req->fd;
    }
}

并且把request归入全局变量sapi_globals.server_context,那点很关键,方便了在任啥地点方对须求的调用。

SG(server_context) = (void *) &request;

2、WSGI Application

1.拉开八个 socket 监听服务

fcgi_fd = fcgi_listen(bindpath, 128);

从这里初始监听,而fcgi_listen函数里面则变成 socket
服务前三步socket,bind,listen

  1. Web
    Server运维时载入法斯特CGI进程微电脑(PHP-CGI大概PHP-FPM或然spawn-cgi卡塔尔
  2. 法斯特CGI进度微机自个儿开首化,运营多个CGI解释器进度(可以预知三个php-cgiState of Qatar并等待来自Web
    Server的连接。
  3. 当顾客端央求达到Web
    Server时,FastCGI进度微处理机采用并再而三到三个CGI解释器。Web
    server将CGI意况变量和正规输入发送到法斯特CGI子进度php-cgi。
  4. 法斯特CGI子进度达成管理后将标准输出和错误消息从同一而再再而三接重返Web
    Server。当法斯特CGI子进度关闭连接时,必要便告管理完了。法斯特CGI子进度接着等待并拍卖来自法斯特CGI进程微型机(运营在Web
    Server中卡塔尔国的下三个接连。 在CGI情势中,php-cgi在那便脱离。

写在最后

把 法斯特CGI
的文化学习驾驭的长河做了这样风姿洒脱篇笔记,把温馨知道的内容(自己认为)有系统地写出来,可以让旁人比较轻便看精通也是意气风发件不挺不便于的事。同不时间也让投机对这一个知识点的理解又深入了黄金年代层。对
PHP 代码学习通晓中还会有众多嫌疑之处还亟需自家要好前期慢慢消食和清楚。

本文都以温和的部分知道,水平有限,如有改进,希望我们赋予指正。

同心同德看完本的都是老车手,说真话,前边有个别太单调了!假诺能把种种知识点真正通晓消食,相对收入良多。

WSGI将 web 组件分为三类: web服务器,web中间件,web应用程序,
wsgi基本管理情势为 : WSGI Server -> (WSGI MiddlewareState of Qatar* -> WSGI
Application 。

2.最早化要求对象

fcgi_request对象分配内部存款和储蓄器,绑定监听的 socket 套接字。

fcgi_init_request(&request, fcgi_fd);

全部央求从输入到再次回到,都围绕着fcgi_request布局体对象在进行。

typedef struct _fcgi_request {
    int            listen_socket;
    int            fd;
    int            id;
    int            keep;
    int            closed;

    int            in_len;
    int            in_pad;

    fcgi_header   *out_hdr;
    unsigned char *out_pos;
    unsigned char  out_buf[1024*8];
    unsigned char  reserved[sizeof(fcgi_end_request_rec)];

    HashTable     *env;
} fcgi_request;

PHP-FPM

法斯特CGI 协议剖析

下边结合 PHP 的 法斯特CGI 的代码举办解析,不作特殊表明以下代码均来自于 PHP
源码。

Spawn-FCGI是二个通用的法斯特CGI管理服务器,它是lighttpd中的生龙活虎部份,很几人都用Lighttpd的Spawn-FCGI举办法斯特CGI形式下的管理专门的学问,不过有广大捷笔。而PHP-FPM的面世些微减轻了有的主题材料,但PHP-FPM有个破绽正是要重新编写翻译,那对于有个别曾经运转的意况也可能有非常大的危机卡塔尔(قطر‎,在php
5.3.3中得以一直运用PHP-FPM了。Spawn-FCGI的代码比超级少,全体才630行,用c语言编写,近日二次提交是5年前。代码主页:

历史观 CGI 职业原明白析

客商端访问有些 UHavalL 地址然后,通过 GET/POST/PUT 等方法提交数据,并透过
HTTP 公约向 Web 服务器发出央浼,服务器端的 HTTP Daemon(守护过程)将
HTTP 诉求里描述的音讯通过规范输入 stdin 和景况变量(environment
variable卡塔尔传递给主页钦赐的 CGI
程序,并运维此应用程序实行管理(包含对数据库的处理),管理结果通过正式输出
stdout 再次回到给 HTTP Daemon 守护进度,再由 HTTP Daemon 进度经过 HTTP
公约再次回到给顾客端。

上面包车型客车这段话通晓大概如故相比空虚,下边大家就通过一遍GET供给为例举行详细表达。

奥门新浦京官方网站 5

上面用代码来促成图中公布的效率。Web 服务器运转三个 socket
监听服务,然后在地点推行 CGI 程序。前边有比较详细的代码解读。

PHP-FPM是七个PHP 法斯特CGI微型机,是只用于PHP的,能够在

进度微处理器)用于替换 PHP-CGI
的大部增大功效,对于高负载网址是特别管用的。它的功能富含:

3.创立多少个 CGI 深入解析器子进度

此地子进度的个数暗中同意是0,从配置文件中读取设置到碰到变量,然后在程序中读取,然后创制钦命数量的子进度来等待管理Web 服务器的央求。

if (getenv("PHP_FCGI_CHILDREN")) {
    char * children_str = getenv("PHP_FCGI_CHILDREN");
    children = atoi(children_str);
    ...
}

do {
    pid = fork();
    switch (pid) {
    case 0:
        parent = 0; // 将子进程中的父进程标识改为0,防止循环 fork

        /* don't catch our signals */
        sigaction(SIGTERM, &old_term, 0);
        sigaction(SIGQUIT, &old_quit, 0);
        sigaction(SIGINT,  &old_int,  0);
        break;
    case -1:
        perror("php (pre-forking)");
        exit(1);
        break;
    default:
        /* Fine */
        running++;
        break;
    }
} while (parent && (running < children));

法斯特CGI是一个可伸缩地、高速地在HTTP
server和动态脚本语言间通讯的接口。多数流行的HTTP
server都扶植法斯特CGI,包含Apache、Nginx和lighttpd等,同不经常间,法斯特CGI也被多数脚本语言探究所匡助,当中就有PHP。

Web 服务器代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>

#define SERV_PORT 9003

char* str_join(char *str1, char *str2);
char* html_response(char *res, char *buf);

int main(void)
{
    int lfd, cfd;
    struct sockaddr_in serv_addr,clin_addr;
    socklen_t clin_len;
    char buf[1024],web_result[1024];
    int len;
    FILE *cin;

    if((lfd = socket(AF_INET,SOCK_STREAM,0)) == -1){
        perror("create socket failed");
        exit(1);
    }

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(SERV_PORT);

    if(bind(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
    {
        perror("bind error");
        exit(1);
    }

    if(listen(lfd, 128) == -1)
    {
        perror("listen error");
        exit(1);
    }

    signal(SIGCLD,SIG_IGN);

    while(1)
    {
        clin_len = sizeof(clin_addr);
        if ((cfd = accept(lfd, (struct sockaddr *)&clin_addr, &clin_len)) == -1)
        {
            perror("接收错误n");
            continue;
        }

        cin = fdopen(cfd, "r");
        setbuf(cin, (char *)0);
        fgets(buf,1024,cin); //读取第一行
        printf("n%s", buf);

        //============================ cgi 环境变量设置演示 ============================

        // 例如 "GET /user.cgi?id=1 HTTP/1.1";

        char *delim = " ";
        char *p;
        char *method, *filename, *query_string;
        char *query_string_pre = "QUERY_STRING=";

        method = strtok(buf,delim);         // GET
        p = strtok(NULL,delim);             // /user.cgi?id=1 
        filename = strtok(p,"?");           // /user.cgi

        if (strcmp(filename,"/favicon.ico") == 0)
        {
            continue;
        }

        query_string = strtok(NULL,"?");    // id=1
        putenv(str_join(query_string_pre,query_string));

        //============================ cgi 环境变量设置演示 ============================

        int pid = fork();

        if (pid > 0)
        {
            close(cfd);
        }
        else if (pid == 0)
        {
            close(lfd);
            FILE *stream = popen(str_join(".",filename),"r");
            fread(buf,sizeof(char),sizeof(buf),stream);
            html_response(web_result,buf);
            write(cfd,web_result,sizeof(web_result));
            pclose(stream);
            close(cfd);
            exit(0);
        }
        else
        {
            perror("fork error");
            exit(1);
        }
    }

    close(lfd);

    return 0;
}

char* str_join(char *str1, char *str2)
{
    char *result = malloc(strlen(str1)+strlen(str2)+1);
    if (result == NULL) exit (1);
    strcpy(result, str1);
    strcat(result, str2);

    return result;
}

char* html_response(char *res, char *buf)
{
    char *html_response_template = "HTTP/1.1 200 OKrnContent-Type:text/htmlrnContent-Length: %drnServer: mengkangrnrn%s";

    sprintf(res,html_response_template,strlen(buf),buf);

    return res;
}

实则不管服务器程序,middleware
照旧应用程序,都在服务端,为顾客端提供劳务,之所以把她们抽象成差异层,正是为了垄断复杂度,使得每贰次都不太复杂,各司其职。

ISAPI(Internet Server Application Program
Interface)是微软提供的生龙活虎套面向WEB服务的API接口,它能兑现CGI提供的全套功能,并在那功底上海展览中心开了扩展,如提供了过滤器应用程序接口。ISAPI应用大多数以DLL动态库的样式利用,能够在被客商央浼后实施,在管理完一个顾客乞请后不会即时消失,而是继续驻留在内存中等待处理其他客户输入。别的,ISAPI的DLL应用程序和WEB服务器高居同一个进程中,成效要简明高于CGI。(由于微软的排他性,只好运转于windows遭受State of Qatar

原先,如何抉择合适的Web应用程序框架成为麻烦Python初读书人的一个题目,那是因为,平日来讲,Web应用框架的取舍将范围可用的Web服务器的拈轻怕重,反之亦然。那个时候的Python应用程序平常是为CGI,法斯特CGI,mod_python中的几个而规划,以至是为特定Web服务器的自定义的API接口而设计的。WSGI未有官方的兑现,
因为WSGI更像二个合计。只要依据那一个公约,WSGI应用(Application卡塔尔(قطر‎都得以在别的服务器(Server卡塔尔上运维,
反之亦然。WSGI便是Python的CGI包装,相对于法斯特cgi是PHP的CGI包装。

  1. uWSGI的根本特点如下:
  2. 超级快的性质。
  3. 低内部存款和储蓄器占用(实地衡量为apache2的mod_wsgi的十分之五左右)。
  4. 多app管理。
  5. 详尽的日志效用(能够用来解析app质量和瓶颈)。
  6. 可观可定制(内部存款和储蓄器大小约束,服务一定次数后重启等)。
  1. spawn-fcgi 首先create socket,bind,listen
    3步创造服务器socket,(把那么些socket叫做 fcgi_fd)
  2. 用dup2,把fcgi_fd 交换给 FCGI_LISTENSOCK_FILENO
    (FCGI_LISTENSOCK_FILENO数值上等于0,那是fastcgi合同在那之中钦赐用来listen的socket
    id)
  3. 实施execl ,replaces the current process image with a new process
    image. process image 进度在运作空间的代码段

wsgi application正是三个平日的callable对象,当有诉求到来时,wsgi
server会调用这一个wsgi
app。那几个指标吸取三个参数,常常为environ,start_response。environ就如前边介绍的,可以清楚为情况变量,跟三遍呼吁相关的全部新闻都保留在了这一个碰着变量中,包含服务器音讯,顾客端音信,央求消息。start_response是二个callback函数,wsgi
application通过调用start_response,将response headers/status 重回给wsgi
server。其余这几个wsgi app会return 叁个iterator对象
,那几个iterator便是response
body。这么空讲以为很虚,对着上边这一个差相当少的例子看就理解相当多了。

  1. php-cgi更动php.ini配置后需重启php-cgi技巧让新的php-ini生效,无法平滑重启
  2. 直接杀死php-cgi进度php就不可能运转了。(PHP-FPM和Spawn-FCGI就从未有过这一个难题,守护进程会平滑从新兴成新的子进度。)

CGI即通用网关接口(Common Gateway
Interface卡塔尔国,是外界应用程序(CGI程序)与Web服务器之间的接口标准,是在CGI程序和Web服务器之间传递音讯的规程。CGI标准允许Web服务器实践外界程序,并将它们的出口发送给Web浏览器,CGI将Web的朝气蓬勃组大致的静态超媒体文书档案形成三个完好无损的新的人机联作式媒体。通俗的讲CGI就好像意气风发座桥,把网页和WEB服务器中的实施顺序连接起来,它把HTML选取的一声令下传递给服务器的实行顺序,再把服务器试行顺序的结果返还给HTML页。CGI 的跨平台质量极佳,大约能够在任何操作系统上贯彻。

FastCGI

WSGI

Spawn-FCGI代码解析如下:

Spawn-FCGI是多个很开始时期的次第,远瞻一下就能够。其余有:1997年的大器晚成段代码:

PHP-CGI是PHP自带的FastCGI管理器。PHP-CGI的不足:

WSGI区分为七个部份:风度翩翩为“服务器”或“网关”,另风流罗曼蒂克为“应用程序”或“应用框架”。在拍卖四个WSGI哀告时,服务器会为应用程序提供条件信息及叁个回呼函数(Callback
Function)。当应用程序完毕管理乞求后,透过前述的回呼函数,将结果回传给服务器。所谓的
WSGI
中间件同期落到实处了API的双方,由此能够在WSGI服务和WSGI应用之间起调节效率:从WSGI服务器的角度来讲,中间件扮演应用程序,而从应用程序的角度来讲,中间件扮演服务器。“中间件”组件能够举行以下功用:

Spawn-FCGI

ISAPI

奥门新浦京官方网站 6

CGI脚本工作流程:

 码字很麻烦,转发请注脚来源标点符的《网关心下一代组织议学习:CGI、法斯特CGI、WSGI》

法斯特CGI的做事流程:

Spawn-FCGI功效很单纯:

wsgi server能够知晓为叁个合乎wsgi标准的web
server,选拔request央浼,封装大器晚成多级意况变量,依照wsgi规范调用注册的wsgi
app,最终将response再次回到给顾客端。文字很难解释清楚wsgi
server到底是何等东西,以至做些什么业务,最直观的不二等秘书技恐怕看wsgi
server的实今世码。以python自带的wsgiref为例,wsgiref是依据wsgi标准落到实处的二个简短wsgi
server。它的代码也不复杂。

3、WSGI MiddleWare

uWSGI

  1. 服务器成立socket,监听端口,等待客商端连接。
  2. 当有诉求来时,服务器解析客商端新闻放到景况变量environ中,并调用绑定的handler来管理诉求。
  3. handler分析那几个http央浼,将呼吁新闻举个例子method,path等放到environ中。
  4. wsgi
    handler再将一些劳动器端音讯也置于environ中,最后服务器音讯,客商端消息,此番要求音讯全部都保留到了情形变量environ中。
  5. wsgi handler 调用注册的wsgi app,并将environ和回调函数字传送给wsgi app
  6. wsgi app 将reponse header/status/body 回传给wsgi handler
  7. 终极handler照旧通过socket将response音讯塞回给客商端。

稍微效果与利益大概在于服务器程序和应用程序之间,例如,服务器获得了顾客端央浼的UXC60L,
差别的UTucsonL供给交由差异的函数管理,那几个意义叫做 U兰德PRADOL
Routing,那个作用就可以投身二者中间完毕,那个中间层就是middleware。middleware对服务器程序和接受是透明的,也正是说,服务器程序感觉它正是应用程序,而应用程序感到它正是服务器。这就告知大家,middleware必要把温馨伪装成四个服务器,接收应用程序,调用它,同期middleware还要求把团结伪装成多少个应用程序,传给服务器程序。

  1. 浏览器通过HTML表单或超链接须要指向叁个CGI应用程序的U瑞鹰L。
  2. 服务器收发到央浼。
  3. 服务器试行所钦赐的CGI应用程序。
  4. CGI应用程序实践所需求的操作,平日是基于浏览者输入的始末。
  5. CGI应用程序把结果格式化为网络服务器和浏览器可以精晓的文档(日常是HTML网页)。
  6. 互连网服务器把结果重临到浏览器中。

1、WSGI Server/gateway

  1. 重写境况变量后,依据指标UHavalL,将呼吁新闻路由到不一致的施用对象。
  2. 同意在三个历程中何况运转八个应用程序或利用框架。
  3. 负载均衡和长间隔管理,通过在互联网上转账号召和响应音讯。
  4. 张开内容后甩卖,比如利用XSLT样式表。

发表评论

电子邮件地址不会被公开。 必填项已用*标注