【问题标题】:fastcgi_finish_request creates hung connection when open session exists存在打开会话时,fastcgi_finish_request 创建挂起的连接
【发布时间】:2015-04-10 23:24:01
【问题描述】:

我有一个客户端发送一个需要很长处理时间的请求,客户端用 ajax 发送请求。一旦请求在服务器上被接受,客户端就会重定向到另一个页面,这是由 fastcgi_finish_request 完成的(我正在运行 php-fpm)

LongWork.php:

<?php
    fastcgi_finish_request(); 
    sleep(1000); //Simulate long computation time
?>

client.js:

$.ajax({
    url: "...",
    data: {},
    success: function() {
        top.location.href="next_page.php" 
    }
});

ajax 被发送并且成功回调导致重定向到 next_page.php 如预期的那样。

然后页面停止,直到睡眠结束我才得到任何服务。看起来我的连接正在等待 same php-fpm 进程完成

我正在使用 php-fpm 运行 nginx,知道为什么会发生这种情况吗?

编辑

经过更多调查,我发现这种行为的原因是我有一个活动会话(来自 facebook SDK),当我在 LongWork.php 上销毁会话时:

<?php
    session_destroy(); // Session was halting the client from accessing another page
    fastcgi_finish_request(); 
    sleep(1000); //Simulate long computation time
?>

您能否考虑一下这个解决方案?

我应该做一些不同于session_destroy()的事情

编辑:

根据 Lachlan Pease 的评论,我已将 session_destroy 切换为 session_write_close

【问题讨论】:

  • 客户端是否使用 Internet Explorer? - 我相信除非您发送至少 255 个字符,否则它不会终止连接 - 尽管这可能只是旧版本。不知道,没用过。
  • @Leigh 问题是服务器上的会话,这在每个客户端都会重现,请参阅有问题的编辑
  • @ekeren,您应该能够使用 session_write_close() 而不是 session_destroy() 来解决这个问题 - 也就是说,我仍然会向 PHP 提交一个关于此的错误,这不是完全预期的行为编辑:实际上,考虑一下,这是预期的行为 - 默认情况下,如果用户的会话已经打开,PHP 将阻止。相反,您可以尝试仅在需要时在后续页面上打开会话;立即运行 session_start() 已成为习惯,但使用输出缓冲可以按需启动它而不会产生不良影响。
  • @LachlanPease 谢谢,它也有效。 session_destory 和 session_write_close 有什么区别?
  • @ekeren 不同的是 session_destroy 会删除服务器上的会话数据(即删除实际存储会话数据的文件),这样当你进入下一页时,用户会有一个空白会话。相比之下, session_write_close(或 session_commit,它的其他名称)只会将会话数据写入磁盘并释放 PHP 持有的锁。之后,对 $_SESSION 的任何新更改都不会更改,但在下一次请求时将可以使用其中的任何内容。

标签: ajax nginx session-state php


【解决方案1】:

问题在于会话存在,有关更多详细信息,请参阅问题中的编辑

【讨论】:

    【解决方案2】:

    我也遇到过这个问题, 我注册了一个由 register_shutdown_function 运行的函数, 和函数开始 which fastcgi_finish_request ,而我发现 fastcgi_finish_request() 之后的脚本仍然阻塞用户的页面,同时放置 session_destroy();在 fastcgi_finish_request() 之前;确实有效,并且用户的页面不再阻塞。

    【讨论】: