我有一些新的 Web 服务器,其中运行着 ubuntu 22 LTS、apache2 和 php-fpm,以及 mpm_event。
它们的表现都一样。apache 运行 8-12 天后。它突然停止接收请求,直到我手动重新启动 apache2。然后它又正常运行了 10 天。
它会随机崩溃
这是 netstat 的输出 Apache 似乎只监听 tcp6? 好像不对。。它不应该监听普通的 tcp 吗?
netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 729/systemd-resolve
tcp 0 0 0.0.0.0:22825 0.0.0.0:* LISTEN 2728/php
tcp 0 0 0.0.0.0:23004 0.0.0.0:* LISTEN 2752/php
tcp 0 0 0.0.0.0:22928 0.0.0.0:* LISTEN 2742/php
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1072/sshd: /usr/sbi
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 971/mysqld
tcp 0 0 127.0.0.1:33060 0.0.0.0:* LISTEN 971/mysqld
tcp6 0 0 :::9100 :::* LISTEN 1074312/node_export
tcp6 71 0 :::80 :::* LISTEN 2207/apache2
tcp6 0 0 :::22 :::* LISTEN 1072/sshd: /usr/sbi
tcp6 512 0 :::443 :::* LISTEN 2207/apache2
udp 0 0 127.0.0.53:53 0.0.0.0:* 729/systemd-resolve
udp 0 0 0.0.0.0:500 0.0.0.0:* 1073/charon
udp 0 0 0.0.0.0:4500 0.0.0.0:* 1073/charon
udp6 0 0 :::500 :::* 1073/charon
udp6 0 0 :::4500 :::* 1073/charon
我也做了堆栈跟踪。
strace -o apache.strace -f -p 2207
输出:
2207 times({tms_utime=3026 /* 30.26 s */, tms_stime=6010 /* 60.10 s */, tms_cutime=369020 /* 3690.20 s */, tms_cstime=174724 /* 1747.24 s */}) = 1819843146
2207 pselect6(0, NULL, NULL, NULL, {tv_sec=1, tv_nsec=0}, NULL) = 0 (Timeout)
2207 wait4(-1, 0x7ffedc77b084, WNOHANG|WSTOPPED, NULL) = 0
2207 times({tms_utime=3026 /* 30.26 s */, tms_stime=6010 /* 60.10 s */, tms_cutime=369020 /* 3690.20 s */, tms_cstime=174724 /* 1747.24 s */}) = 1819843246
2207 pselect6(0, NULL, NULL, NULL, {tv_sec=1, tv_nsec=0}, NULL) = 0 (Timeout)
2207 wait4(-1, 0x7ffedc77b084, WNOHANG|WSTOPPED, NULL) = 0
2207 times({tms_utime=3026 /* 30.26 s */, tms_stime=6010 /* 60.10 s */, tms_cutime=369020 /* 3690.20 s */, tms_cstime=174724 /* 1747.24 s */}) = 1819843346
2207 pselect6(0, NULL, NULL, NULL, {tv_sec=1, tv_nsec=0}, NULL) = 0 (Timeout)
2207 wait4(-1, 0x7ffedc77b084, WNOHANG|WSTOPPED, NULL) = 0
2207 times({tms_utime=3026 /* 30.26 s */, tms_stime=6010 /* 60.10 s */, tms_cutime=369020 /* 3690.20 s */, tms_cstime=174724 /* 1747.24 s */}) = 1819843446
2207 pselect6(0, NULL, NULL, NULL, {tv_sec=1, tv_nsec=0}, NULL) = 0 (Timeout)
2207 wait4(-1, 0x7ffedc77b084, WNOHANG|WSTOPPED, NULL) = 0
2207 times({tms_utime=3026 /* 30.26 s */, tms_stime=6010 /* 60.10 s */, tms_cutime=369020 /* 3690.20 s */, tms_cstime=174724 /* 1747.24 s */}) = 1819843546
2207 pselect6(0, NULL, NULL, NULL, {tv_sec=1, tv_nsec=0}, NULL) = 0 (Timeout)
2207 wait4(-1, 0x7ffedc77b084, WNOHANG|WSTOPPED, NULL) = 0
2207 times({tms_utime=3026 /* 30.26 s */, tms_stime=6010 /* 60.10 s */, tms_cutime=369020 /* 3690.20 s */, tms_cstime=174724 /* 1747.24 s */}) = 1819843646
2207 pselect6(0, NULL, NULL, NULL, {tv_sec=1, tv_nsec=0}, NULL) = 0 (Timeout)
2207 wait4(-1, 0x7ffedc77b084, WNOHANG|WSTOPPED, NULL) = 0
2207 times({tms_utime=3026 /* 30.26 s */, tms_stime=6010 /* 60.10 s */, tms_cutime=369020 /* 3690.20 s */, tms_cstime=174724 /* 1747.24 s */}) = 1819843747
2207 pselect6(0, NULL, NULL, NULL, {tv_sec=1, tv_nsec=0}, NULL) = 0 (Timeout)
2207 wait4(-1, 0x7ffedc77b084, WNOHANG|WSTOPPED, NULL) = 0
2207 times({tms_utime=3026 /* 30.26 s */, tms_stime=6010 /* 60.10 s */, tms_cutime=369020 /* 3690.20 s */, tms_cstime=174724 /* 1747.24 s */}) = 1819843847
2207 pselect6(0, NULL, NULL, NULL, {tv_sec=1, tv_nsec=0}, NULL) = 0 (Timeout)
2207 wait4(-1, 0x7ffedc77b084, WNOHANG|WSTOPPED, NULL) = 0
2207 times({tms_utime=3026 /* 30.26 s */, tms_stime=6010 /* 60.10 s */, tms_cutime=369020 /* 3690.20 s */, tms_cstime=174724 /* 1747.24 s */}) = 1819843947
2207 pselect6(0, NULL, NULL, NULL, {tv_sec=1, tv_nsec=0}, NULL) = 0 (Timeout)
2207 wait4(-1, 0x7ffedc77b084, WNOHANG|WSTOPPED, NULL) = 0
它就这样永远循环下去。
这是 iptables 设置
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -i eth0 -p tcp -m multiport --dports 22345:25000 -m conntrack --ctstate NEW -j ACCEPT
ip6tables:
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p ipv6-icmp -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -i eth0 -p tcp -m multiport --dports 22345:25000 -m conntrack --ctstate NEW -j ACCEPT
答案1
这是 PHP 堆栈中工作线程耗尽的典型症状。这通常意味着通过模块运行 php 的 Apache 工作线程在等待某些事情时被阻塞(最常见,但不是唯一原因)- 代码中的某个地方有一个对外部 Web 服务器的 curl 请求,而超时没有明确设置为某个低且合理的值,例如 10 秒)。一旦所有工作线程都处于等待状态,Apache 就会达到工作线程分叉的限制并停止处理新连接。
这种情况并不特定于将 PHP 作为模块运行的 Apache - 它可能发生在各种堆栈中,例如 nginx+php-fpm。
PS 当 Linux 内核有一个套接字,某个应用程序在 ipv4 和 ipv6 地址系列上监听时,它显示为在 tcp6 上监听。