Multithreading 多线程FastCGI应用程序

Multithreading 多线程FastCGI应用程序,multithreading,cgi,fastcgi,Multithreading,Cgi,Fastcgi,我想写一个FastCGI应用程序,它应该使用线程处理多个并发请求。我查看了SDK附带的示例: #define THREAD_COUNT 20 static int counts[THREAD_COUNT]; static void *doit(void *a) { int rc, i, thread_id = (int)a; pid_t pid = getpid(); FCGX_Request request; char *server_name; F

我想写一个FastCGI应用程序,它应该使用线程处理多个并发请求。我查看了SDK附带的示例:

#define THREAD_COUNT 20
static int counts[THREAD_COUNT];

static void *doit(void *a)
{
    int rc, i, thread_id = (int)a;
    pid_t pid = getpid();
    FCGX_Request request;
    char *server_name;

    FCGX_InitRequest(&request, 0, 0);

    for (;;)
    {
        static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER;
        static pthread_mutex_t counts_mutex = PTHREAD_MUTEX_INITIALIZER;

        /* Some platforms require accept() serialization, some don't.. */
        pthread_mutex_lock(&accept_mutex);
        rc = FCGX_Accept_r(&request);
        pthread_mutex_unlock(&accept_mutex);

        if (rc < 0)
            break;

        server_name = FCGX_GetParam("SERVER_NAME", request.envp);

        FCGX_FPrintF(request.out,…
        …     

        FCGX_Finish_r(&request);
    }

    return NULL;
}

int main(void)
{
    int i;
    pthread_t id[THREAD_COUNT];

    FCGX_Init();

    for (i = 1; i < THREAD_COUNT; i++)
        pthread_create(&id[i], NULL, doit, (void*)i);

    doit(0);

    return 0;
}
#定义线程数20
静态整数计数[线程计数];
静态void*doit(void*a)
{
int rc,i,thread_id=(int)a;
pid_t pid=getpid();
FCGX_请求;
字符*服务器名称;
FCGX_InitRequest(&request,0,0);
对于(;;)
{
静态pthread\u mutex\u t accept\u mutex=pthread\u mutex\u初始值设定项;
静态pthread\u mutex\u t counts\u mutex=pthread\u mutex\u初始值设定项;
/*有些平台需要accept()序列化,有些则不需要*/
pthread_mutex_lock(&accept_mutex);
rc=FCGX\u接受请求(&r);
pthread_mutex_unlock(&accept_mutex);
if(rc<0)
打破
server_name=FCGX_GetParam(“server_name”,request.envp);
FCGX_FPrintF(请求输出,…
…     
FCGX_完成_r(&请求);
}
返回NULL;
}
内部主(空)
{
int i;
pthread_t id[线程计数];
FCGX_Init();
对于(i=1;i
在中有一个解释,web服务器将如何确定FastCGI应用程序支持的连接数:

Web服务器可以查询特定的 应用程序中的变量 服务器通常会执行查询 在应用程序启动时,为了 自动化系统的某些方面 配置

•FCGI_MAX_CONNS:最大数量 并发传输连接的定义 此应用程序将接受,例如“1” 或“10”

•FCGI_MAX_需求:最大数量 这是并发请求的数量 申请将接受,例如“1”或 “50”

•FCGI_MPXS_接头:“0”如果 应用程序不能多路复用 连接(即处理并发 每个连接上的请求),“1” 否则

但是这个查询的返回值是硬编码到FastCGI SDK中的,对于FCGI_MAX_CONNS和FCGI_MAX_REQS,返回1;对于FCGI_MPXS_CONNS,返回0。因此threaded.c示例永远不会接收多个连接


我使用lighttpd和nginx测试了该示例,该应用程序一次只处理一个请求。我如何让我的应用程序处理多个请求?或者这是一种错误的方法?

我认为您的测试方式可能会将您限制为单线程。我曾遇到过类似的情况,使用libfcgi和lighttpd,但确定如果使用Firefox进行测试时,Firefox会人为地限制向服务器提交HTTP请求,直到向同一服务器提交上一个请求完成为止。您用于测试的工具可能会执行类似的操作

您不需要修改
FCGI_MAX_CONNS
FCGI_MAX_REQS
、或
FGCI_MPXS_CONNS
。硬编码的值对nginx或lighttpd等现代web服务器不重要

使用命令行工具,例如,一次生成20个curl进程以全部命中服务器,结果是在SDK提供的示例threaded.c上运行时,所有20个线程都被激活,并且所有20个curl进程在2秒后同时完成(该示例具有显式的
sleep(2)
调用)

我的lighttpd配置设置如下:

fastcgi.server = (
    "/test" => (
        "test.fastcgi.handler" => (
            "socket" => "/tmp/test.fastscgi.socket",
            "check-local" => "disable",
            "bin-path" => "/tmp/a.fastcgi",
            "max-procs" => 1,
        )
    )
)
max procs
设置为1只会生成fcgi程序的一个副本,lighttpd应报告在前一个请求完成之前请求传入时套接字上的“负载”增加


如果生成21个卷曲进程,前20个应在2秒内完成,然后最后一个应在另外2秒内完成。生成40个卷曲进程所需的时间应与生成21个卷曲进程所需的时间几乎相同(总共超过4秒)-

20个请求,20个并行请求,耗时2秒-

$ http_load -parallel 20 -fetches 20 request.txt
20 fetches, 20 max parallel, 6830 bytes, in 2.0026 seconds
341.5 mean bytes/connection
9.98701 fetches/sec, 3410.56 bytes/sec
msecs/connect: 0.158 mean, 0.256 max, 0.093 min
msecs/first-response: 2001.5 mean, 2002.12 max, 2000.98 min
HTTP response codes:
  code 200 -- 20
$ http_load -parallel 20 -fetches 21 request.txt
21 fetches, 20 max parallel, 7171 bytes, in 4.00267 seconds
341.476 mean bytes/connection
5.2465 fetches/sec, 1791.55 bytes/sec
msecs/connect: 0.253714 mean, 0.366 max, 0.145 min
msecs/first-response: 2001.51 mean, 2002.26 max, 2000.86 min
HTTP response codes:
  code 200 -- 21
$ http_load -parallel 20 -fetches 40 request.txt
40 fetches, 20 max parallel, 13660 bytes, in 4.00508 seconds
341.5 mean bytes/connection
9.98732 fetches/sec, 3410.67 bytes/sec
msecs/connect: 0.159975 mean, 0.28 max, 0.079 min
msecs/first-response: 2001.86 mean, 2002.62 max, 2000.95 min
HTTP response codes:
  code 200 -- 40
21个请求,20个并行请求,耗时4秒-

$ http_load -parallel 20 -fetches 20 request.txt
20 fetches, 20 max parallel, 6830 bytes, in 2.0026 seconds
341.5 mean bytes/connection
9.98701 fetches/sec, 3410.56 bytes/sec
msecs/connect: 0.158 mean, 0.256 max, 0.093 min
msecs/first-response: 2001.5 mean, 2002.12 max, 2000.98 min
HTTP response codes:
  code 200 -- 20
$ http_load -parallel 20 -fetches 21 request.txt
21 fetches, 20 max parallel, 7171 bytes, in 4.00267 seconds
341.476 mean bytes/connection
5.2465 fetches/sec, 1791.55 bytes/sec
msecs/connect: 0.253714 mean, 0.366 max, 0.145 min
msecs/first-response: 2001.51 mean, 2002.26 max, 2000.86 min
HTTP response codes:
  code 200 -- 21
$ http_load -parallel 20 -fetches 40 request.txt
40 fetches, 20 max parallel, 13660 bytes, in 4.00508 seconds
341.5 mean bytes/connection
9.98732 fetches/sec, 3410.67 bytes/sec
msecs/connect: 0.159975 mean, 0.28 max, 0.079 min
msecs/first-response: 2001.86 mean, 2002.62 max, 2000.95 min
HTTP response codes:
  code 200 -- 40
40个请求,20个并行请求,耗时4秒-

$ http_load -parallel 20 -fetches 20 request.txt
20 fetches, 20 max parallel, 6830 bytes, in 2.0026 seconds
341.5 mean bytes/connection
9.98701 fetches/sec, 3410.56 bytes/sec
msecs/connect: 0.158 mean, 0.256 max, 0.093 min
msecs/first-response: 2001.5 mean, 2002.12 max, 2000.98 min
HTTP response codes:
  code 200 -- 20
$ http_load -parallel 20 -fetches 21 request.txt
21 fetches, 20 max parallel, 7171 bytes, in 4.00267 seconds
341.476 mean bytes/connection
5.2465 fetches/sec, 1791.55 bytes/sec
msecs/connect: 0.253714 mean, 0.366 max, 0.145 min
msecs/first-response: 2001.51 mean, 2002.26 max, 2000.86 min
HTTP response codes:
  code 200 -- 21
$ http_load -parallel 20 -fetches 40 request.txt
40 fetches, 20 max parallel, 13660 bytes, in 4.00508 seconds
341.5 mean bytes/connection
9.98732 fetches/sec, 3410.67 bytes/sec
msecs/connect: 0.159975 mean, 0.28 max, 0.079 min
msecs/first-response: 2001.86 mean, 2002.62 max, 2000.95 min
HTTP response codes:
  code 200 -- 40
因此,它证明了即使FCGI_MAX_CONNS、FCGI_MAX_REQS和FCGI_MPXS_CONNS值是硬编码的,请求也是并行的

当Nginx接收到多个请求时,它会将它们背靠背地放在FCGI应用程序的队列中。在发送第二个请求之前,它不会等待第一个请求的响应。在FCGI应用程序中,当一个线程在任何时间为第一个请求提供服务时,另一个线程不会等待第一个请求完成,它将拿起第二个请求并开始处理它。依此类推


因此,您将损失的唯一时间是从队列中读取请求所需的时间。与处理请求所需的时间相比,此时间通常可以忽略不计。

这个问题没有一个答案,因为这不仅取决于FastCGI协议,而且最重要的是,还取决于中的FastCGI进程管理器使用。对于Apache2 web服务器,FastCGI进程管理器通常可能是
mod_FastCGI
mod_fcgid
。两者的行为都不同。
mod_FastCGI
似乎具有多线程意识,并将向声明支持它的FastCGI服务器发送并发请求。
mod_fcgid
到目前为止(将来可能会更改?)不支持多线程,并且将始终根据并发请求生成新的FastCGI服务器进程,并且永远不会向FastCGI服务器发送并发请求

所有这些都表明:是的,FastCGI提供了多线程FastCGI服务器,但运行FastCGI服务器的环境也必须实现这一功能……在prac中