我刚刚开始理解apache服务器是如何工作的,有一天我在编写一个非常简单的网页时遇到了问题,同时显示了页面的点击数:
/* The simplest HelloWorld module */
#include <httpd.h>
#include <http_protocol.h>
#include <http_config.h>
static int noOfViews = 0;
static int helloworld_handler(request_rec *r)
{
if (!r->handler || strcmp(r->handler, "helloworld")) {
return DECLINED;
}
if (r->method_number != M_GET) {
return HTTP_METHOD_NOT_ALLOWED;
}
noOfViews++;
ap_set_content_type(r, "text/html;charset=ascii");
ap_rputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n",
r);
ap_rputs("<html><head><title>Apache HelloWorld "
"Module</title></head>", r);
ap_rputs("<body><h1>Hello World!</h1>", r);
ap_rputs("<p>This is the Apache HelloWorld module!</p>", r);
ap_rprintf(r, "<p>Views: %d</p>", noOfViews);
ap_rputs("</body></html>", r);
return OK;
}
static void helloworld_hooks(apr_pool_t *pool)
{
ap_hook_handler(helloworld_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA helloworld_module = {
STANDARD20_MODULE_STUFF,
NULL,
NULL,
NULL,
NULL,
NULL,
helloworld_hooks
};
基本上发生的事情是当我刷新页面时,点击计数器会上升,但有时它会随机下降。有人告诉我,这是因为Apache Prefork MPM的工作方式。看完之后:
http://httpd.apache.org/docs/2.0/mod/prefork.html
我更了解这个问题,但我仍然不能100%肯定会发生什么。因此prefork MPM创建了一堆子进程,其中一些空闲,并等待客户端连接,所以当我刷新页面时,我实际上连接到服务器正在运行的一堆不同的子进程。但是,此模块具有有限数量的子进程,它可以同时保持,因此有时当它杀死进程时我的计数器会关闭。我不完全确定这个解释是否正确,或者为什么计数器完全失效。
感谢所有建议。
答案 0 :(得分:0)
是的,无论是那个,还是你有一个其他的Apache进程在柜台出现故障时为你提供服务。
您可以尝试以这样一种方式配置Apache:它只生成一个永远存在的1个子进程,但通过这样做,您可以限制Apaches功能。
我建议您尝试让模块完全无状态。如果您想要该计数器,请将状态保存在文件或数据库中,并在需要时从那里检索它。您甚至可以与另一个具有命中计数器的进程进行对话,该进程只是在您的模块中的静态变量中。
答案 1 :(得分:0)
您将命中计数存储在noOfViews变量中,这意味着在单个进程的内存中。
无论是在worker还是prefork MPM下,httpd通常会生成多个子进程。每个都有自己的noOfViews内存存储,所以你只计算该进程的命中数。当您的请求被随机分配给其他进程时,它会有一个不同的计数器。
你会发现prefork比worker更多,因为每个prefork进程一次只处理一个请求,而worker是线程化的,可以处理多个;所以prefork下的进程比worker更多。但是当你的请求被引导到不同的进程时,在MPM下也会发生同样的事情。
另请注意,重新启动httpd或仅删除单个进程会丢失计数器。新流程将从0开始。因此,如果您的目标是统计全球点击量,这不是一个好方法。