【原創】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發行版(比較高的版本)。

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