用于处理服务器端事件的PHP服务器导致Apache连接过多

PHP server for handling Server Side Events causes too many Apache connections

本文关键字:Apache 连接 服务器 服务器端 处理 事件 PHP 用于      更新时间:2023-09-26

我有一个响应服务器端事件的PHP服务器进程,可以将其视为一个仪表板更新脚本。

它基本上每隔几秒钟向一个仪表板页面发送一次数据(JSON),该页面使用SSE(服务器端事件)来显示仪表板。问题是过了一段时间,PHP进程就死了,但被重新生成了(这是SSE协议的一部分),这很好,但不知怎么的,它让我的Web服务器在几个小时后看起来像这样。。。

 PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command
 2954 root       20   0 22372  2140  1244 R  1.0  0.1  0:00.06 htop
 2952 root       20   0 70160  3584  2684 S  1.0  0.2  0:00.05 sshd: root [priv]
    1 root       20   0 10648   692   648 S  0.0  0.0  1:33.93 init [2]
  378 root       20   0 21348  1044   772 S  0.0  0.1  0:00.28 udevd --daemon
 1164 www-data   20   0  354M 16616  6200 S  0.0  0.8  0:00.00 /usr/sbin/apache2 -k start
 1165 www-data   20   0  354M 16616  6200 S  0.0  0.8  0:03.32 /usr/sbin/apache2 -k start
 1077 www-data   20   0  354M 16616  6200 S  0.0  0.8  0:03.35 /usr/sbin/apache2 -k start
 1115 www-data   20   0  356M 19704  6404 S  0.0  1.0  0:00.00 /usr/sbin/apache2 -k start
 1116 www-data   20   0  356M 19704  6404 S  0.0  1.0  0:02.87 /usr/sbin/apache2 -k start
 1079 www-data   20   0  356M 19704  6404 S  0.0  1.0  0:02.93 /usr/sbin/apache2 -k start
 1542 www-data   20   0  292M 18796  6516 S  0.0  0.9  0:00.00 /usr/sbin/apache2 -k start
 1543 www-data   20   0  292M 18796  6516 S  0.0  0.9  0:01.93 /usr/sbin/apache2 -k start
 1455 www-data   20   0  292M 18796  6516 S  0.0  0.9  0:01.98 /usr/sbin/apache2 -k start
 1811 www-data   20   0  360M 26516 12636 S  0.0  1.3  0:00.00 /usr/sbin/apache2 -k start
 1812 www-data   20   0  360M 26516 12636 S  0.0  1.3  0:01.87 /usr/sbin/apache2 -k start
 1669 www-data   20   0  360M 26516 12636 S  0.0  1.3  0:01.98 /usr/sbin/apache2 -k start
 1713 www-data   20   0  354M 13160  2992 S  0.0  0.6  0:00.00 /usr/sbin/apache2 -k start
 1714 www-data   20   0  354M 13160  2992 S  0.0  0.6  0:02.06 /usr/sbin/apache2 -k start
 1672 www-data   20   0  354M 13160  2992 S  0.0  0.6  0:02.06 /usr/sbin/apache2 -k start
 1879 www-data   20   0  356M 20292  6988 S  0.0  1.0  0:00.00 /usr/sbin/apache2 -k start
 1880 www-data   20   0  356M 20292  6988 S  0.0  1.0  0:01.19 /usr/sbin/apache2 -k start
 .. many more 

首先,我知道PHP不是编写这些长期运行(类似守护进程)的后台服务的理想语言,像NodeJS这样的语言会更合适,但在开发的这一点上,重写所有内容(即没有预算)是不现实的。

所以我的问题是,有什么方法可以防止Apache为这些特定的PHP请求生成新的连接,或者以某种方式重新使用特定的进程来维护这个PHP脚本。。本质上,当SEE请求发生时,将请求缓存到单个Apache进程。。。感谢

默认情况下,在JavaScript中,服务器端事件内置了错误处理。此错误处理的一部分包括在SSE事件句柄关闭(有意或意外)时重新连接到服务器。默认的重新连接时间约为3秒。根据本网站,在大多数浏览器实现中:HTML 5 Rocks

根据链接,服务器可以在其回复中指定客户端在尝试重新连接之前应等待的重试时间(如果您希望覆盖约3秒的默认值)。下面是一个例子:

retry: 10000'n
data: hello world'n'n

这对你有什么帮助

在这一点上,你可能想知道这对你有什么帮助。好问题。正如您所注意到的,Apache并不是真正为持久连接(如SSE或套接字事件)而构建的。为了在PHP中适应这一点,每次发送回数据回复时,都可以指定一个retry头,如上面所示。然后在脚本结束时调用CCD_ 2。PHP将完成,Apache将关闭连接,但一旦错误处理重新连接执行,SSE链将继续。

这绝不是最优雅的解决方案。事实上,它类似于使用AJAX的长轮询方法。然而,您可以放心,浏览器将在不必编写自定义处理的情况下启动重新连接,并且它仍然使用SSE API结构,使您更容易在以后(如果需要)将服务器端代码移植到Node.js之类的代码,而无需修改前端代码。

请注意,这不会像您在上面的问题中提到的那样缓存连接。不过,它应该有助于缓解您的问题,允许Apache清理"等待"的连接,从而为新的调用释放这些连接。

@War10ck的回答很好。

我还建议将KeepAliveTimeout减少到几秒钟(如果你需要从同一个vhost提供许多其他文件),或者完全禁用KeepAlive(如果它主要用于SSE,并且你不需要小文件的性能)。这将允许Apache更快地"清理"这些连接。