摘要 本文在Linux 2.6.9平台下,针对Apache Web Server实现了关键性能参数的在线调节,使得网络管理员能在服务繁忙的情况下,不用重起服务就能调节服务器的性能参数,减少因为重起服务引起的经济损失。
关键词 Web服务器 Apache 共享内存 在线调节
Abstract: Thispaper designs and implements an online parameter-tuning system for Apache web server under Linux 2.6.9 platform. This system enables the web administrator to tuning the performance parameters of server without restarting the web service, hence reduces the cost caused by restarting the web service.
Keywords: Web Server Apache shared memory online tuning
1 引言
Apache是如今Internet上最流行的web服务器。Netcraft的调查表明,世界上超过60%的网络Web服务器都使用Apache作为Web服务软件。Apache是一个开放源代码(Open Source)软件,它健壮、高效、模块化、响应速度快,并且可靠稳定。
Web管理员可以通过调节Apache配置文件中的性能参数来调节和优化服务器的性能,然而这种方法只能实现静态调节,一旦服务器启动,对配置文件中的任何参数修改只有在重新启动服务器的情况下才能起作用。在网络服务繁忙的情况下重新启动服务器需要付出代价,因为在重起的过程中会拒绝某些服务,在电子商务中拒绝服务往往会引起经济损失。该文阐述在Linux平台下如何实现Apache参数在线调节,使得管理员可以根据负载情况动态调节服务器的性能参数以提高web服务的性能,避免重新启动服务带来的损失。
2 Apache服务器简介
本文使用的是Apache 2.0.52版本,相对于Apache 1.3版本来说,Apache 2.0更容易移植,更加可靠,它完全基于模块。Apache 2.0的多道处理模块(mpm)的引入使得用户可以根据不同站点的特点和需求来选择安装不同的mpm来实现不同的运行方式。Apache2.0.52中的mpm模块有:
1. 预先派生(prefork)
2. 工作者(worker)
3. WinNT
4. beos
5. os2
6. netware
7. 独立子进程(perchild)
8. 领导者(leader)
9. 线程池(threadpool)
其中后三个是试验模块,而前六个已经比较成熟稳定,3,4,5,6这四个mpm主要是针对对应的操作系统设计的。prefork模块是多进程预先派生模块,而工作者(worker)模块以多进程多线程的方式工作。本文中使用的是prefork模块。
3 Apache配置参数简介
在apache的配置文件httpd.conf中提供了很多可供web管理员配置的性能参数,其中最大子进程数(MaxClients)和KeepAliveTimeout(保持连接超时)是对服务器性能影响最大的两个参数。
MaxClients如果设的过小,则在连接多的情况下,客户就得排队等候,造成了系统资源没有充分利用。而MaxClients如果设的过大,服务器就会超负载运行,从而使得整体性能下降。
KeepAliveTimeout是主要是针对http1.1连接请求所设置的参数。它设置了在两次连接请求之间所等待的时间,如果两次连接请求之间间隔超过KeepAliveTimeout,服务器就断开本次连接。
KeepAliveTimeout如果设的过小的话,保持连接的优势无法发挥。而KeepAliveTimeout如果设的过大,由于一个子进程一次只能处理一个连接,造成了子进程被绑在某个连接上,从而造成资源浪费,并且在负载重的情况下,造成很多用户需要排队等候,而CPU却空闲的现象。
4 在线参数调节系统的实现
4.1 Apache服务器的工作方式
要实现Apache的在线参数调节,首先要了解Apache的工作方式。本文使用的mpm是prefork,因此着重介绍prefork的工作方式。
prefork模块是多进程模块,启动时,由父进程派生出多个子进程,父进程是管理进程,它按照配置文件的配置参数来控制子进程数,处理异常退出的子进程并向日志中记录出错情况,维护服务器的正常运转,它并不直接处理连接请求。服务器的连接请求是由派生出来的子进程进行处理的。父进程和子进程间通过记分板(scoreboard)进行通信。
记分板实际上是一段共享内存,它记录了一些全局的信息例如进程数上限(server_limit)和线程数上限(thread_limit),并且它还维护着每个工作子进程或线程的情况如进程号(pid),线程号(thread_num)以及进程或线程所处的状态(status)等。
要从外部程序在线修改apache的性能参数,需要通过读写共享内存记分板来实现。一般需要在共享内存记分板添加各性能参数对应的变量,通过动态修改记分板中的变量来动态调整apache的性能参数。
4.2 读写Apache服务器的共享内存
要从外部程序读写Apache的记分板,首先要了解是操作系统的共享内存机制的以及Apache共享内存中的具体内容。Apache API函数库中有六个宏,可以通过测试这几个宏的值来了解操作系统的共享内存机制,这几个宏是:
1. APR_USE_SHMEM_MMAP_ZERO
2. APR_USE_SHMEM_MMAP_ANON
3. APR_USE_SHMEM_SHMGET_ANON
4. APR_USE_SHMEM_MMAP_TMP
5. APR_USE_SHMEM_MMAP_SHM
6. APR_USE_SHMEM_SHMGET
其中前三个是匿名共享内存的创建方式,后三个是有名共享内存的创建方式,其中1,2,4,5这四个宏是Posix共享内存方式,而3,6是System V共享内存方式。
通过测试,Linux 2.6.9系统上所使用的是APR_USE_SHMEM_MMAP_ANON和APR_USE_SHMEM_SHMGET。
通过设置配置文件中的ScoreboardFile选项使服务器使用有名共享内存,即System V的共享内存机制。这样apache所使用的共享内存shmid可以通过在root权限下执行ipcs命令获得。
至于共享内存的内容,Apache源代码中有一个名为记分板的数据结构,其结构如下:
typedef struct{
global_score *global;
process_score *parent;
worker_score **servers;
}scoreboard;
而共享内存记分板中的内容如图1所示,在共享内存的起始处有一
图1 .Apache 共享内存记分板的内容
因此读取记分板内容首地址的伪代码如下(如果采用Posix有名共享内存机制的话):
{
Char* m;
m=shmat(shmid,NULL,0);
}
从而我们可以通过获取的共享内存首地址m对共享内存进行读写访问,有目的地修改记分板的内容。
4.3 Apache源代码的修改
我们只介绍maxclients参数的在线调节的实现。
首先在global_score结构中增加一个变量my_daemons_limit,该结构存在于记分板头文件scoreboard.h中,该文件类似地定义了与记分板内容有关的结构变量如process_score,worker_score等。
在scoreboard.c中将my_daemons_limit的初始值设置为配置文件中配置的maxclients参数值,这主要通过ap_mpm_query函数来实现,代码为:
Ap_mpm_query(AP_MPMQ_MAX_DAEMON_USED,& my_daemons_limit)
为了使其它程序访问到真实的最大子进程数即记分板中的my_daemons_limit值,在ap_mpm.h中添加一个宏AP_MPMQ_MY_MAX_DAEMON_USED,并且在prefork.c的ap_mpm_query函数的适当位置添加以下代码:
Case AP_MPMQ_MY_MAX_DAEMON_USED:
*result=ap_scoreboard_image->global->my_daemons_limit;
return APR_SUCCESS;
同时将其它文件中调用Ap_mpm_query(AP_MPMQ_MAX_DAEMON_USED,…)函数的地方改为Ap_mpm_query(AP_MPMQ_MY_MAX_DAEMON_USED,…).
改动较大的是在prefork.c中,除了ap_mpm_query和set_max_clients函数中的ap_daemons_limit保持不变外,其它地方的ap_daemons_linit应相应改为ap_scoreboard_image->global->my_daemons_limit,比较特别的一处是在perform_idle_server_maintainance中应改为server_limit因为该循环是查询记分板中的各个进程状态并设置相应的计数值,而外部程序设置的最大子进程数可能比初始值大也可能比初始值小。
在perform_idle_server_maintainance中还应该修改相应的代码以控制活动子进程数(total_non_dead)不超过my_daemons_limit.
至此,通过对apache源代码的修改和重新编译安装后,我们可以根据4.2节的方法编写外部程序来随意修改性能参数的值。伪代码如下:
{
Char* m;
Global_score* global;
m=shmat(shmid,NULL,0);
global= (global_score*)m;
set(global->my_daemons_limit);
shmctl(shmid,IPC_RMID,0);
exit(0);
}
5 结论与展望
本文在Linux 2.6.9平台下,针对Apache Web Server实现了关键性能参数的在线调节,使得系统管理员能在服务繁忙的情况下,不用重起服务就能调节服务器的性能参数,减少因为重起服务引起的经济损失。
我们还可以通过动态调节参数程序的进一步编写来实现在线检测负载大小并根据目前的系统资源使用状况自动调节参数的功能,这是我们进一步要完成的工作。
参考文献
1. Ryan B.Bloom 着.袁勤勇,何欣等译.Apache Server 2.0技术参考大全.清华大学出版社,2003
2. W.Richard Stevens着.杨继张译.Unix网络编程-第2卷:进程间通信.清华大学出版社,2000
3. Y Diao, N Gandhi, JL Hellerstein et al.Using MIMO Feedback Control to Enforce Policies for Interrelated Metrics With Application to the Apache Web Server. Network Operations and Management Symposium,2002
4. Apache Software Foundation.http://www.apache.org
本文作者: