快速CGI中"multiplexing"的含义是什么?



FastCGI规范的附录B给出了一个多路复用的例子,其中未缩进的行是由客户端(例如Nginx)发送的,缩进的行是由FastCGI服务器发送的:

{FCGI_BEGIN_REQUEST,   1, {FCGI_RESPONDER, FCGI_KEEP_CONN}}
{FCGI_PARAMS,          1, "1302SERVER_PORT801316SERVER_ADDR199.170.183.42 ... "}
{FCGI_PARAMS,          1, ""}
{FCGI_BEGIN_REQUEST,   2, {FCGI_RESPONDER, FCGI_KEEP_CONN}}
{FCGI_PARAMS,          2, "1302SERVER_PORT801316SERVER_ADDR199.170.183.42 ... "}
{FCGI_STDIN,           1, ""}
{FCGI_STDOUT,      1, "Content-type: text/htmlrnrn"}
{FCGI_PARAMS,          2, ""}
{FCGI_STDIN,           2, ""}
{FCGI_STDOUT,      2, "Content-type: text/htmlrnrn<html>n<head> ... "}
{FCGI_STDOUT,      2, ""}
{FCGI_END_REQUEST, 2, {0, FCGI_REQUEST_COMPLETE}}
{FCGI_STDOUT,      1, "<html>n<head> ... "}
{FCGI_STDOUT,      1, ""}
{FCGI_END_REQUEST, 1, {0, FCGI_REQUEST_COMPLETE}}

根据我的理解,在上面的非复用版本中,FastCGI客户端(例如Nginx)将在发送与请求2相关的任何内容之前发送请求1:

(图2):

{FCGI_BEGIN_REQUEST,   1, {FCGI_RESPONDER, FCGI_KEEP_CONN}}
{FCGI_PARAMS,          1, "1302SERVER_PORT801316SERVER_ADDR199.170.183.42 ... "}
{FCGI_PARAMS,          1, ""}
{FCGI_STDIN,           1, ""}
{FCGI_STDOUT,      1, "Content-type: text/htmlrnrn"}
{FCGI_STDOUT,      1, "<html>n<head> ... "}
{FCGI_STDOUT,      1, ""}
{FCGI_END_REQUEST, 1, {0, FCGI_REQUEST_COMPLETE}}
{FCGI_BEGIN_REQUEST,   2, {FCGI_RESPONDER, FCGI_KEEP_CONN}}
{FCGI_PARAMS,          2, "1302SERVER_PORT801316SERVER_ADDR199.170.183.42 ... "}
{FCGI_PARAMS,          2, ""}
{FCGI_STDIN,           2, ""}
{FCGI_STDOUT,      2, "Content-type: text/htmlrnrn<html>n<head> ... "}
{FCGI_STDOUT,      2, ""}
{FCGI_END_REQUEST, 2, {0, FCGI_REQUEST_COMPLETE}}

我的理解正确吗?

我在一些地方读到Nginx不支持FastCGI的多路复用:

  • fastcgi复用?
  • 为什么Nginx不实现FastCGI多路复用?

然而,这似乎与多线程FastCGI App相矛盾,其中提到Nginx在发送第二个请求之前不会等待第一个请求的响应,就像这样:

(图3):

{FCGI_BEGIN_REQUEST,   1, {FCGI_RESPONDER, FCGI_KEEP_CONN}}
{FCGI_PARAMS,          1, "1302SERVER_PORT801316SERVER_ADDR199.170.183.42 ... "}
{FCGI_PARAMS,          1, ""}
{FCGI_STDIN,           1, ""}
{FCGI_BEGIN_REQUEST,   2, {FCGI_RESPONDER, FCGI_KEEP_CONN}}
{FCGI_PARAMS,          2, "1302SERVER_PORT801316SERVER_ADDR199.170.183.42 ... "}
{FCGI_PARAMS,          2, ""}
{FCGI_STDIN,           2, ""}

我在这一点上感到困惑,因为从我的理解,一个非多路版本应该一次只处理一个请求(即接收请求,并在处理下一个请求之前为该请求发送响应)。多路复用的确切含义是什么?特别是:

  • 非多路复用是否允许在对旧请求给出响应之前接受新请求?(例如,参考下面的代码片段,请参见在给出响应A之前接受请求B)。

    (图4):

    {Request A}
    {Request B}
    {Response A}
    {Request C}
    {Response C}
    {Response B}
    
  • 非多路复用是否允许以与请求不同的顺序给出响应?(例如请求顺序:A, B, C;响应顺序:A, C, B).

  • 多路复用是否意味着请求的部分可以与其他请求和响应的部分混合在一起?例如

    (图5):

    {Small part of request A}
    {Small part of request B}
    {Small part of request A}
    {Small part of request B}
    {Small part of response A}
    {Small part of request B}
    {Small part of response B}
    ...
    

请注意,我是网络和FastCGI的新手。

如果没有多路复用,nginx在收到新请求时,只需要建立一个新的连接到fastcgi listen套接字。多个请求以任何顺序并行处理,但是每个连接一次只携带一个请求的数据。这与HTTP/1和许多其他协议的处理方式完全相同。