【问题标题】:long running PHP script Apache-FPM does not return response to client长时间运行的 PHP 脚本 Apache-FPM 不向客户端返回响应
【发布时间】:2021-08-04 09:14:57
【问题描述】:

我放弃了尝试在 heroku 上使用 Apache-FPM 调试此问题。

我有一个运行大约 10 分钟的 php 安装脚本。脚本预计需要很长时间。

一个简单的 Ajax 客户端 javascript 调用向我的 PHP 脚本发出 POST 请求,脚本成功运行,并在脚本结束时将内容回显给客户端。

jQuery.ajax({
        url: 'longrunningscript.php',
        method: 'POST',
        timeout: 0,
        data: {
            'something': 'something'
        },
        success: function(result) {
            debugger;
            console.log(result);
            
        },
        error: function(jqXHR,textStatus,errorThrown) {
            debugger;
            console.log(textStatus + ' ' + errorThrown);
            
        },
        complete: function(jqXHR,textStatus) {
            console.log(textStatus);
        }
    })

服务器端配置。注意那些包括调试设置

我的 apache server 2.4 配置了

Timeout 1200
ProxyTimeout 1200
KeepAlive Off
<Directory />
    Options FollowSymlinks
    AllowOverride All
    Require all granted
</Directory>
LogLevel trace6
DirectoryIndex index.php

我的 php 是使用 `.user.ini 配置的

max_execution_time = 0
max_input_time = 0
default_socket_timeout = -1
memory_limit = 256M
display_errors = On
bcmath.scale = 2
short_open_tag = On
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE
post_max_size = 100M
log_errors = On
max_input_vars = 5000
output_buffering = on

php-fpm 配置为

request_terminate_timeout = 0
request_slowlog_timeout = 0
catch_workers_output = true
php_admin_flag[fastcgi.logging] = On
php_admin_flag[file_uploads] = On
php_admin_value[max_file_uploads] = 200
php_admin_value[max_execution_time] = 0
php_admin_value[max_input_time] = 0
php_admin_value[default_socket_timeout] = -1
php_admin_flag[log_errors] = On
php_admin_value[opcache.log_verbosity_level] = 3

longrunningscript.php 脚本很简单

set_time_limit(0);
session_start();
ob_start();
longrunningprocessstarts();
// Unset all of the session variables.
$_SESSION = array();
session_destroy();
session_write_close();
//output

$content = ob_get_contents();

// Erase the buffer in case we want to use it for something else later
if (ob_end_clean()) {
    header("Connection: close");
    header('Content-Encoding: gzip');
    header('Language: en-US');
    header("Content-Length: " . strlen($content));
// All of the data that was in the buffer is now in $content
    http_response_code(200);
    echo $content;
  //  flush();
    fastcgi_finish_request();
}

服务器端绝对没有发生超时,服务器处于 LogLevel trace6 并且没有警告,没有错误,所有信息看起来都正常。 它在成功完成请求后将 /POST 请求记录在日志中并显示日志 (收回)

[http:trace3] [pid 378:tid 140551512872704] http_filters.c(1126): [client x.x.x.x:x] Response sent with status 200, headers:

Date:  app[web.1]: [a time] 
[http:trace5] [pid 378:tid 140551512872704] http_filters.c(1138): [client x.x.x.x:x]   Server: Apache
[http:trace4] [pid 378:tid 140551512872704] http_filters.c(956): [client x.x.x.x:x]   Expires: A date GMT
[http:trace4] [pid 378:tid 140551512872704] http_filters.c(956): [client x.x.x.x:x]    Cache-Control: no-store, no-cache, must-revalidate
[http:trace4] [pid 378:tid 140551512872704] http_filters.c(956): [client x.x.x.x:x]    Pragma: no-cache
[http:trace4] [pid 378:tid 140551512872704] http_filters.c(956): [client x.x.x.x:x]    Connection: close
[http:trace4] [pid 378:tid 140551512872704] http_filters.c(956): [client x.x.x.x:x]    Content-Encoding: gzip
[http:trace4] [pid 378:tid 140551512872704] http_filters.c(956): [client x.x.x.x:x]    Language: en-US
[http:trace4] [pid 378:tid 140551512872704] http_filters.c(956): [client x.x.x.x:x]    
Set-Cookie: PHPSESSID=deleted; expires=Date GMT; Max-Age=0; path=/
[http:trace4] [pid 378:tid 140551512872704] http_filters.c(956): [client x.x.x.x:x]    Content-Length: 1786
[http:trace4] [pid 378:tid 140551512872704] http_filters.c(956): [client x.x.x.x:x]    Content-Type: text/html; charset=UTF-8
[date time] [proxy:debug] [pid 378:tid 140551512872704] proxy_util.c(2453): AH00943: FCGI: has released connection for (heroku-fcgi)

Apache 2.4、PHP 7.4.22

我把这个问题隔离了这么多(现在使用普通的 Postman POST 请求)

问题出在哪里?!是 Apache 还是 FPM / PHP 还是我在 http 请求/响应中做错了什么?

我的下一步是对实际的 http 通信本身进行故障排除,我不知道该怎么做。

请注意,我不是在寻找替代方法来解决像 websocket 等长期运行的脚本。我想找出这个问题的根本原因是什么,响应基本“消失”在哪里。

【问题讨论】:

  • 浏览器是否超时?你的客户怎么说?从我目前发现的情况来看,例如 chrome 的最大超时时间为 5 分钟。
  • @CodeSpirit 我不再使用 Chrome 进行测试——我转而使用 Postman(它也可能使用 Chrome 设置,因为它只是一个浏览器包装器)。然而,除了网络选项卡之外,Chrome 中没有任何信息,它显示“请求正在运行”。 Chrome 中的最大超时在哪里?这是使用 Ajax 调用,并且上面的 Timeout=0
  • 您遇到了客户端超时。您可以做的事情是在刷新之间为浏览器提供一些数据。检查这个例子:stackoverflow.com/questions/3133209/…

标签: php ajax apache fpm


【解决方案1】:

确实 chrome 在内部关闭了连接,超时在 5 分钟后。最佳解决方案是确保调用时间短,并以不同方式管理表单提交。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 2014-09-13
    • 1970-01-01
    相关资源
    最近更新 更多