Multithreading 多线程FastCGI应用程序
我想写一个FastCGI应用程序,它应该使用线程处理多个并发请求。我查看了SDK附带的示例: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
#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中