服务器在PhP 7.4中发送了事件SSE-Apache挂起并且没有注册/服务任何新请求



上下文

我正在运行一个PhP服务器发送的事件应用程序,该应用程序运行在PhP 7.4和Ubuntu 20.10上的Apache 2.4上。该应用程序可以执行它应该执行的操作,但可能是用户数量的增加(连接?SSE连接?)导致服务器挂起。我期望/希望能够处理相对大量的用户(约1000),但我的SSE事件很少触发(15分钟内约3次),并且只查找和发送服务器上文本文件中的一些字符串值。

问题

我的问题是,在某些情况下,包括客户端数量增加(约70到100)Apache开始挂起。新的HTTP请求不会在访问日志中报告,错误日志中也不会报告任何错误,并且从浏览器发送的任何请求似乎永远都在加载,没有服务器响应此时服务器负载(处理器、RAM)最小并且我可以正常地通过SSH或FTP访问服务器。

我尝试过的

默认的Apache配置会发生这种情况,因此根据在线建议,我尝试关闭mpm_prefork模块激活mpm_event和php7.4-fpm。除了客户端数量增加几十个之外,没有太大变化,但这也可能不是真的,因为我无法手动测试,只要有机会就对应用程序进行实时测试。

我已经尝试关闭应用程序中的SSE元素,在这种情况下,我没有Apache挂起问题(但我无法更新需要SSE的客户端信息)。这意味着SSE可能会导致重载/Apache挂起,但我不知道是什么。

我认为Apache挂起与打开的连接或进程的数量有关。据我所知,我只能在/etc/apache2/apache2.conf(我尝试设置MaxKeepAliveRequests0)和etc/php/7.4/fpm/pool.d/www.conf中控制它(我尝试将

pm.max_children设置为250,pm.start_servers=10,pm.min_pare_servers=5,pm.max_spare_servers=15,pm.max_requests=1000我的问题

  • 我能做些什么来增加Apache支持的连接数/SSE进程运行数
  • 我该怎么做才能找出是什么导致Apache挂起,或者通常是什么导致挂起
  • 关于如何解决Apache挂起问题,还有其他想法/建议

我的服务器端代码是

<?php
header('Content-Type: text/event-stream; charset=utf-8');
header("Cache-Control: no-store");
header('Connection: keep-alive');
header('Content-Encoding: none;');
set_time_limit(0);
while (true) {

if (configurationChanged()) {
echo "data: " . newConfiguration() . "nn";
ob_end_flush();
flush();

} else {
sleep(3);  
}

if (connection_aborted()) break;
}
?>

我的客户代码是

var source = new EventSource('myScript.php', {withCredentials: false});
source.onopen = function (event) {
console.log("Connection opened.");
};
source.onmessage = function(event) {
console.log(event.data);
// Do stuff with the obtained data here
}

感谢您阅读本文。

解决方案

我的主要问题是,当我的服务器上有可用的资源时,我没想到Apache会挂起。缺乏经验导致我浪费了很多小时才意识到我应该在中寻找原因

  • Apache错误日志/var/log/apache2/error.log
  • FPM日志/var/log/php7.4-FPM.log

我尝试根据注释中给出的链接重新配置mpm事件模块。虽然它有助于将并发用户数量增加几十个,但当用户数量进一步增加时,同样的问题开始出现

有帮助的是在/etc/php/7.4/fpm/pool.d/www.conf中设置pm=ondemand,以避免手动定义参数。我不知道为什么这不是默认的,或者没有得到更广泛的推荐。我的问题似乎得到了解决。

然而,一个新的问题开始出现。FPM log/var/log/php7.4-FPM.log开始报告两种错误:

  1. [mpm_event:error]。。。AH03490:记分板已满,未达到MaxRequestWorkers。请增加ServerLimit这会让我的web应用程序为用户挂起几分钟,然后在没有任何干预的情况下恢复正常
  2. [proxy_fcgi:error]。。。(70007)指定的超时已过期:。。。AH01075:将请求调度到(轮询)时出错,referr:这将为我的用户杀死我的web应用程序(因此,如果SSE连接结束,我添加了JavaScript来向我的用户重新加载目标php脚本)

对于1。我试图按照错误消息说明";增加服务器限制";并添加";ServerLimit 250〃;到/etc/apache2/mods-enabled/mpm_event.conf。这并没有解决问题。我发现了这个Apache错误报告,但我使用的是本应修复的版本。然后我发现这个页面建议我应该将mpm事件更改为mpm worker。像符咒一样工作,解决了问题1。

对于2。问题2与我的PhP SSE应用程序有关,特别是SSE脚本超时。没有帮助的只是简单地添加set_time_limit(0)到我的PhP脚本。proxy_fcgi根据错误达到了超时,所以我必须编辑/etc/apache2/apache2.conf并设置超时3600代理超时3600

这将任何脚本的最长执行时间增加到1小时(3600秒)。这不是一个理想的解决方案,但我还没能找到一个只允许特定脚本(在我的例子中是运行在无限循环中的SSE PhP脚本)执行时间的解决方案。

希望这能帮助到别人!