我有PHP服务器进程响应服务器端事件,将其视为仪表板更新脚本。
它基本上每隔几秒就将数据(JSON)发送到一个仪表板页面,该页面利用SSE(服务器端事件)来显示仪表板。问题是一段时间之后PHP进程终止,但重新生成(这是SSE协议的一部分),这很好,但不知怎的,它让我的网络服务器在几个小时后看起来像这样......
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脚本。本质上,将请求缓存到单个Apache进程时SEE请求发生...谢谢
答案 0 :(得分:1)
默认情况下,在JavaScript中,服务器端事件内置了错误处理。此错误处理的一部分包括在关闭SSE事件句柄(故意或意外)时重新连接到服务器。默认重新连接时间约为3秒。在根据此站点的大多数浏览器实现中:HTML 5 Rocks
根据链接,服务器在其回复中可以指定客户端在尝试重新连接之前应等待的重试时间,如果您希望覆盖约3秒的默认值。下面是一个例子:
retry: 10000\n
data: hello world\n\n
这对您有何帮助?
您可能想知道这对您有何帮助。好问题。正如您所知,Apache并非真正构建用于SSE或套接字事件等持久性连接。为了在PHP中容纳这一点,每次发回数据回复时,都可以指定retry
标题,如上所示。然后在脚本调用结束时exit
。 PHP将完成,Apache将关闭连接,但一旦错误处理和重新连接执行,SSE链将继续。
绝不是最优雅的解决方案。实际上,它类似于使用AJAX的长轮询方法。但是,您确实有内置的安心,浏览器将启动重新连接,而无需编写自定义处理,它仍然使用SSE API结构,使您更容易将服务器端代码移植到类似 Node.js 稍后(如果需要),无需修改前端代码。
请注意,这不会像您在问题中提到的那样缓存连接。尽管允许Apache清理等待"等待的连接,但它应该有助于缓解您的问题。释放这些连接以进行新的呼叫。
答案 1 :(得分:0)
@ War10ck的答案很好。
我还建议reducing KeepAliveTimeout只需几秒钟(如果你需要提供来自同一个虚拟主机的许多其他文件)或disabling KeepAlive altogether(如果它主要用于SSE,你不需要小文件的性能)。这将允许Apache清理"清理"这些联系更快。