【原创】Apache在linux AS3上使用会造成CPU使用率达到100%问题一例

故障环境:
    Red Hat Enterprise Linux AS release 3 (Taroon Update 4)
    kernel-2.4.21-27.EL
    glibc-2.3.2-95.30
    apache-2.0.53

[root@test10 root]# /usr/apache2/bin/httpd -V
Server version: Apache/2.0.53
Server built:   Sep  9 2005 16:27:28
Server's Module Magic Number: 20020903:9
Architecture:   32-bit
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D HTTPD_ROOT="/usr/apache2"
 -D SUEXEC_BIN="/usr/apache2/bin/suexec"
 -D DEFAULT_PIDLOG="logs/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="logs/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"

故障现象:
    在Linux AS 3上使用压力测试工具进行测试有时出现httpd子进程CPU占用率100%,且压力撤除后无法恢复,始终有个别httpd子进程CPU占用率很高。但在Linux AS 4上测试始终不会出现此问题,另外使用Jmeter测试在两种系统上均未出现该现象。

问题初步分析:
    由于在Linux AS 4上未出现问题,所以可以确定测试工具和测试脚本不会存在问题。打开Apache监视页面发现CPU占用率高的子进程的状态为Reading,在Apache官方Bugzilla上也有人出现的同样的问题不过有一例已经解决(是由于自身模块的原因,但是没有具体说明)。

问题的进一步分析:
    由于不能通过一些外部表现来继续跟踪,所以只能借助于GDB了。在Apache帮助中有调试相关的介绍,所以就按部就班当故障出现时使用GDB把故障进程的调用堆栈显示出来(如下):
(gdb) bt
#0  0x002738a0 in _IO_un_link_internal () from /lib/tls/libc.so.6
#1  0x0027496c in _IO_default_finish_internal () from /lib/tls/libc.so.6
#2  0x002713ad in _IO_new_file_finish () from /lib/tls/libc.so.6
#3  0x002666d5 in fclose@@GLIBC_2.1 () from /lib/tls/libc.so.6
#4  0x004f3523 in CPakReader::Close () from /usr/lib/httpd/modules/mod_pak.so
#5  0x004f2c50 in CPakReader::~CPakReader () from /usr/lib/httpd/modules/mod_pak.so
#6  0x004f3e29 in mod_pak_method_handler () from /usr/lib/httpd/modules/mod_pak.so
#7  0x0807c2f2 in ap_run_handler (r=0x8a56518) at config.c:153
#8  0x0807c80a in ap_invoke_handler (r=0x8a56518) at config.c:364
#9  0x0806bf8f in ap_process_request (r=0x8a56518) at http_request.c:249
#10 0x08068049 in ap_process_http_connection (c=0x8a523e0) at http_core.c:251
#11 0x0808556e in ap_run_process_connection (c=0x8a523e0) at connection.c:43
#12 0x0807ae6b in child_main (child_num_arg=145082000) at prefork.c:610
#13 0x0807af88 in make_child (s=0x897f800, slot=0) at prefork.c:704
#14 0x0807b06f in startup_children (number_to_start=5) at prefork.c:722
#15 0x0807b77d in ap_mpm_run (_pconf=0x897b0a8, plog=0x89b3188, s=0x897f800) at prefork.c:941
#16 0x08080732 in main (argc=1, argv=0xbfffb324) at main.c:618
接着就是在调用堆栈中自己的模块和相关的函数,然后针对调试该函数,输出更详细的错误信息。此例中出现故障的httpd进程在C库的fclose调用内部可能发生了一个未结束的循环,由于该故障在AS4环境下不存在,据此推定可能是glibc的线程局域存储实现在AS3特有的NPTL环境下有BUG而在某个边界条件下被触发,由堆栈信息可知引发该故障的原因是CPakReader对象析构时调用的fclose,通过增加调试代码发现该处fclose返回了-1(EOF),基本判定为重复关闭已关闭的FILE流指针引发了该故障,因此马上修改后重新测试,问题得以修正。

经验总结:
1、测试时尽量多采用不同的测试工具进行测试,避免由于测试工具的缺陷导致问题潜藏在系统中;
2、对于不经常出现的问题和故障,在发生时尽量保留现场进行分析,并详细记录每次测试的配置条件
3、由于资源泄露和过度释放属代码中高频度发生的BUG,建议开发人员引入一些必要的自动化源代码扫描覆盖手段,尽可能提前发现此类BUG;
4、由于Linux-2.6的核心在原生内核线程支持、进程调度抢占及代码维护等级等方面均优于Linux-2.4核心,且JAVA支持也更加高效,应用部署平台如无特殊要求请尽量使用AS4等使用kernel-2.6.x发行版(比较高的版本)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章