Apache2(搭配mod_jk)单个Worker进程长期未完成优雅重载的原因排查及调试方法咨询
我这边有一台运行Debian 10的服务器,装的是Apache2 2.4.38。最近我替换了所有HTTPS虚拟主机使用的SSL证书,然后执行了systemctl reload apache2.service——这个命令其实是通过systemd单元文件调用/usr/sbin/apachectl graceful来实现优雅重载的。
根据Apache 2的官方文档:
The USR1 or graceful signal causes the parent process to advise the children to exit after their current request (or to exit immediately if they're not serving anything). The parent re-reads its configuration files and re-opens its log files. As each child dies off the parent replaces it with a child from the new generation of the configuration, which begins serving new requests immediately.
在繁忙服务器上,子进程替换有延迟是可以理解的,但今天我发现服务器偶尔还是会返回旧的SSL证书。于是我查看了进程列表:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 13559 0.0 0.2 15640 10356 ? Ss 2022 18:53 /usr/sbin/apache2 -k start www-data 16834 0.7 0.6 1232452 27780 ? Sl 06:00 3:47 /usr/sbin/apache2 -k start www-data 17415 0.9 0.6 1231844 26532 ? Sl 10:22 2:32 /usr/sbin/apache2 -k start www-data 17552 0.7 0.6 1231736 26376 ? Sl 10:53 1:47 /usr/sbin/apache2 -k start www-data 17612 0.6 0.6 1232000 26840 ? Sl 10:54 1:34 /usr/sbin/apache2 -k start www-data 17641 0.6 0.5 1231980 22732 ? Sl 10:54 1:36 /usr/sbin/apache2 -k start www-data 17642 0.8 0.6 1231848 24728 ? Sl 10:54 1:59 /usr/sbin/apache2 -k start www-data 26704 0.5 0.6 1232216 24748 ? Sl Jan18 89:53 /usr/sbin/apache2 -k start
最后这个进程的START和TIME列特别扎眼——我是1月24号执行的重载,现在已经过去6天了,它还在运行。服务器整体响应正常,只是不确定这个卡住的worker是不是还在处理新请求,但其他worker都没问题。
服务器的配置比较简单,用的是默认配置(如果需要具体信息可以随时问我)。唯一值得一提的是它运行了mod_jk:各个VirtualHost指令里都配置了JkMount /* workername,其中workername定义在/etc/libapache2-mod-jk/workers.properties里,mod_jk通过ajp13连接到两台做负载均衡的Tomcat应用服务器。
这不是第一次遇到Apache2 worker卡住的情况了,但我一直没找到原因。我怀疑可能和mod_jk或者那套非常老旧的Java应用有关,也许是某个请求触发了Java/mod_jk层面的罕见边缘case,导致这个worker无法响应USR1信号退出。不过Java应用的日志不在我管控范围内,而且日志内容又多又杂,很多还没时间戳,除非刚好在报错的时候盯着看,否则根本没法用来排查问题。
我知道最后可能只能做非优雅重启,虽然会导致轻微的生产中断,但我更想知道未来有没有更好的方法来调试这类问题,让worker在需要的时候都能可靠地完成优雅重载。大家有什么建议吗?
附服务器相关信息
apachectl -V输出:
Server version: Apache/2.4.38 (Debian) Server built: 2021-12-21T16:50:43 Server's Module Magic Number: 20120211:84 Server loaded: APR 1.6.5, APR-UTIL 1.6.1 Compiled using: APR 1.6.5, APR-UTIL 1.6.1 Architecture: 64-bit Server MPM: event threaded: yes (fixed thread count) forked: yes (variable process count) Server compiled with.... -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 DYNAMIC_MODULE_LIMIT=256 -D HTTPD_ROOT="/etc/apache2" -D SUEXEC_BIN="/usr/lib/apache2/suexec" -D DEFAULT_PIDLOG="/var/run/apache2.pid" -D DEFAULT_SCOREBOARD="logs/apache_runtime_status" -D DEFAULT_ERRORLOG="logs/error_log" -D AP_TYPES_CONFIG_FILE="mime.types" -D SERVER_CONFIG_FILE="apache2.conf"
apachectl -S输出(生产子域名已打码):
VirtualHost configuration: *:443 is a NameVirtualHost default server vhost1.domain.example (/etc/apache2/sites-enabled/00_vhost1.domain.example-ssl.conf:2) port 443 namevhost vhost1.domain.example (/etc/apache2/sites-enabled/00_vhost1.domain.example-ssl.conf:2) port 443 namevhost vhost2.domain.example (/etc/apache2/sites-enabled/01_vhost2.domain.example-ssl.conf:2) port 443 namevhost vhost3.domain.example (/etc/apache2/sites-enabled/02_vhost3.domain.example-ssl.conf:2) port 443 namevhost vhost4.domain.example (/etc/apache2/sites-enabled/03_vhost4.domain.example-ssl.conf:2) alias alias1.domain.example *:80 is a NameVirtualHost default server vhost1.domain.example (/etc/apache2/sites-enabled/00_vhost1.domain.example.conf:1) port 80 namevhost vhost1.domain.example (/etc/apache2/sites-enabled/00_vhost1.domain.example.conf:1) port 80 namevhost vhost2.domain.example (/etc/apache2/sites-enabled/01_vhost2.domain.example.conf:1) alias 172.16.33.63 port 80 namevhost vhost3.domain.example (/etc/apache2/sites-enabled/02_vhost3.domain.example.conf:1) port 80 namevhost vhost4.domain.example (/etc/apache2/sites-enabled/03_vhost4.domain.example.conf:1) alias alias1.domain.example ServerRoot: "/etc/apache2" Main DocumentRoot: "/var/www/html" Main ErrorLog: "/var/log/apache2/error.log" Mutex default: dir="/var/run/apache2/" mechanism=default Mutex watchdog-callback: using_defaults Mutex rewrite-map: using_defaults Mutex ssl-stapling-refresh: using_defaults Mutex ssl-stapling: using_defaults Mutex proxy: using_defaults Mutex ssl-cache: using_defaults PidFile: "/var/run/apache2/apache2.pid" Define: DUMP_VHOSTS Define: DUMP_RUN_CFG User: name="www-data" id=33 Group: name="www-data" id=33
备注:内容来源于stack exchange,提问作者JK Laiho

