什么原因导致单个 Apache2 工作程序(使用 mod_jk)数周无法重新加载?

什么原因导致单个 Apache2 工作程序(使用 mod_jk)数周无法重新加载?

我有一台运行 Apache2 2.4.38 的 Debian 10 服务器。最近,我替换了所有已配置的 HTTPS vhosts 使用的 SSL 证书文件并运行了systemctl reload apache2.service,它/usr/sbin/apachectl graceful通过 systemd 单元文件运行。

根据 Apache 2 文档,

USR1 或优雅信号会导致父进程建议子进程在当前请求之后退出(如果子进程没有提供任何服务,则立即退出)。父进程重新读取其配置文件并重新打开其日志文件。当每个子进程死亡时,父进程会用新一代配置中的子进程替换它,该子进程会立即开始处理新请求。

在繁忙的服务器上,替换子进程的延迟是可以理解的。但是,今天我注意到,服务器很少会使用替换前的旧 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 日运行了重新加载命令,但现在,六天过去了,这个进程仍在运行。不过,服务器对请求的响应很好——尚不清楚这一个工作进程是否真的在处理新请求,但其他工作进程都在处理。

服务器配置非常简单,并且默认设置足够,因此不在此处列出(目前 - 如果您需要任何特定信息,请询问)。它唯一有趣的功能是它正在运行 mod_jk,即各种VirtualHost指令JkMount /* workernameworkername在 /etc/libapache2-mod-jk/workers.properties 中定义)。mod_jk 用于ajp13连接到运行 Tomcat 的两个负载平衡应用程序服务器之一。

这不是我们第一次遇到 Apache2 工作进程卡住的情况,但我一直无法确定它最终卡住的原因。这可能与 mod_jk 和(非常)传统的 Java 应用程序有关,可能存在一些请求,导致 Java/mod_jk 级别出现罕见的边缘情况错误,并阻止工作进程通过 USR1 信号退出。Java 应用程序日志不在我的控制范围内;它们非常冗长,包含无意义的信息,通常缺少时间戳,并且对于故障排除目的几乎毫无用处,除非您恰好在错误发生的确切时刻查看它们。

我必须进行非正常重启,尽管这会导致轻微的生产中断,但我对将来调试此问题的进一步方法很感兴趣,以便我们可以让工作程序在需要时始终可靠地执行正常重启。我们如何才能更好地分析是什么导致工作程序卡住?


结果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

答案1

第三方模块存在一些问题,不允许 httpd 正常重启子进程,甚至导致服务器无响应。

我在使用 mod_weblogic (mod_wl_24.so) 时也遇到了类似的问题,其他人也报告了 mod_security 也遇到了类似的问题。Apache HTTPD 开发人员曾尝试在第三方模块中解决这些所谓的错误行为。

例如 2.4.4X 对此有几处修复。我会尝试升级到至少 2.4.49 及以上版本,然后再试一次。检查https://downloads.apache.org/httpd/CHANGES_2.4并寻找“mpm_event”。

In 2.4.49
 *) mpm_event: Fix children processes possibly not stopped on graceful
     restart.  PR 63169.  [Joel Self <joelself gmail.com>]
 *) mpm_event: Fix graceful stop/restart of children processes if connections
     are in lingering close for too long.  [Yann Ylavic]

In 2.4.47
 *) mpm_event: Don't reset connections after lingering close, restoring prior
     to 2.4.28 behaviour.  [Yann Ylavic]

如果您不能立即升级,使用 mod_proxy_ajp 也可能会获得更好的结果。

简而言之,答案是如果您使用第三方模块,请尝试将版本升级到至少 2.4.49。


编辑:

之前我忘了提到一种解决方法,即“坚持下去”,直到您可以升级或更改模块,即强制 httpd 永远不要优雅地重启任何子进程。怎么做?

使 MaxSpareThreads 具有与 MaxRequestWorkers 相同的值。并且 MaxConnectionsPerChild 为 0 以允许无限连接,这样 httpd 就不会尝试正常关闭它们。

例子:

MaxSpareThreads 500
MaxRequestWorkers 500
MaxConnectionsPerChild 0

并且永远不要发出平稳重启(某些发行版称之为重新加载),只需重新启动或完全停止/启动。

相关内容