这两天弄个PHP调用 SVN 同步 update 多台服务器更新的程序,为了避免 commit 的时候不会被阻塞卡半天得想个办法只请求触发,而不需要等待程序 update 完成返回结果这样耗时太长,所以研究过了下如何让PHP主动断开连接的方法。搞了一下午,发现很多问题,还好最终还是弄出来了,主要是 Nginx 太坑。。


废话不多说,下面上代码:



/**
* 主动断开与客户端浏览器的连接
* 如果是 Nginx 服务器需要输出大于等于 fastcgi_buffer_size 缓存的数据才能即时输出 header 断开连接, 若还是不行可尝试关闭 gzip
* 如: fastcgi_buffer_size 64k; 即: 需要 64*1024 字符(可多不可少),
* 可使用 str_repeat(' ', 65536); 另外 str_repeat(' ', 6554); 这种方式其实生成速度更慢
* @param null|string $str 当前输出的内容, 若无需输出则设置为空
*/
public function connectionClose($str = null) {
$str = ob_get_contents() . $str;
// 若实际输出内容长度小于该值将可能导致主动断开失败
header('Content-Length: '. strlen($str));
Header::connectionClose();
ob_start();
echo $str;
ob_flush();
flush();
}

补充说明下:

对于 apache 一般没什问题,我一开始在 windows 上用的 xampp 调试的 没发现什么问题,结果到服务器上是 Nginx ,死活不行,崩溃了一下午,后来才反映过来是 Nginx 的 fastcgi_buffer 的问题。

各种情况测试了N多次,应该没什么 BUG 了。。。


另外再说说 ignore_user_abort() 函数的问题

当浏览器关闭后,决定程序是否还会在后台继续执行,(下图的例子中,你在测试时不一定非要设置为永不超时 limit 0 ,设置一两分钟就行了,否则可能重启 HTTP 服务需要很长时间)



简单来说,如果你要用户浏览器关闭后还需要程序继续执行,那么你必须加上下面这句代码:

ignore_user_abort(true);

但根据你后面程序(主要是 while 死循环)的情况不同而有些许不同:

一般在程序中你可以监控连接状态进行控制:

$isAborted = connection_aborted();
$status = connection_status();
if (0 !== $status || $isAborted) {
break;
}

但这两个函数要想正常工作得有个前提,就是你的程序必须要有输出内容,且大于当前WebServer 的输出缓存,这样才会起作用。

如果你只是简单的输出一个空格 echo ’ ‘; 可能得循环几千次才会判断到,所以为了更即时的检测到状态你必须每次循环时输出足够多的内容才会触发状态检测。

所以这里也经常会遇到一个问题:当浏览器断开后,即使没有使用 ignore_user_abort(true); 但因为没有任何输出,导致程序仍然会继续执行,死循环会一直跑,如果设置了超时那还好,否则就真死掉了。


下面贴上测试代码(贴个图主要是为了防盗 嘿嘿~)


set_time_limit(0);

ignore_user_abort(true);

while (1) {
echo str_repeat(' ', 65536);
$isAborted = connection_aborted();
$status = connection_status();
file_put_contents('test.txt', 'time: '. time() .'; abroted:'. $isAborted .'; status: '. $status);
if (0 !== $status || $isAborted) {
break;
}
sleep(2);
}

你可以试试注释掉这句

// echo str_repeat(’ ‘, 65536);

另外

set_time_limit(0); 最好也别用 0

PHP 在 Nginx 下主动断开连接 Connection Close 与 ignore_user_abort 后台运行的更多相关文章

  1. 在HTTP通讯过程中,是客户端还是服务端主动断开连接?

    比如说:IE访问IIS,获取文件,肯定是要建立一个连接,这个连接在完成通讯后,是客户端Close了连接,还是服务端Close了连接.我用程序测模拟IE和IIS,都没有收到断开连接的消息,也就是都没有触 ...

  2. Spring Boot中一个Servlet主动断开连接的方法

    主动断开连接,从而返回结果给客户端,并且能够继续执行剩余代码. 对于一个HttpServletResponse类型的对象response来说,执行如下代码: response.getWriter(). ...

  3. Linux下使命令不受终端断开的影响,保持在后台运行的几种方法及原理

    摘自https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/ 记录一下Linux下使命令不受终端断开的影响,保持在后台运行的几个方法及其原理.当用 ...

  4. linux ------ 使用 screen 后 SSH 断开后程序依旧能在后台运行

    为什么ssh断开后你运行的进程会退出呢? 因为所有进程都得有个父进程.当你ssh到一个服务器上时,打开的shell就是你所有执行命令的父进程. 当你断开ssh连接时,你的命令的父进程就没了.如果处理不 ...

  5. Linux云服务器下Redis安装与部署以及设置redis后台运行

    Redis下载: http://redis.io/download 我下载的4.0.11 上传到服务器 注: 官方的建议是直接在linux下载并解压编译 这里不建议先解压再上传到服务器,之前我这样做, ...

  6. linux下ping加时间戳实时输出到文件 放后台运行

    放后台运行命令:setsid 实时输出命令:unbuffer 加时间戳:awk '{ print $0"\t" strftime("%D_%H:%M:%S",s ...

  7. windows下修改tomcat的startup.bat脚本文件后台运行

    1.修改startup.bat文件 rem Get remaining unshifted command line arguments and save them in the set CMD_LI ...

  8. tcp 服务端如何判断客户端断开连接

    一篇文章:   最近在做一个服务器端程序,C/S结构.功能方面比较简单就是client端与server端建立连接,然后发送消息给server.我在server端会使用专门的线程处理一条socket连接 ...

  9. Nginx中的长连接

    在nginx中,对于http1.0与http1.1是支持长连接的 我们知道,http请求是基于TCP协议之上的,那么,当客户端在发起请求前,需要先与服务端建立TCP连接,而每一次的TCP连接是需要三次 ...

随机推荐

  1. JVM内存划分

    JVM内存划分吗? 前言: 大家都知道虚拟机,都知道JVM,其实这些都是基于sun公司[oracle公司]的HotSpot虚拟机,当然本篇博文也是以sun公司为基础.还有其他的虚拟机,常见的就有JRo ...

  2. [原]逆向iOS SDK -- _UIImageAtPath 的实现(SDK 6.1)

    汇编代码: ; 状态:R0 = imageFileName, R1 = mainBundle, R2 = isRetina PUSH    {R4-R7,LR} ; R0 = imageFileNam ...

  3. [置顶] 学习JDK源码:可进一步优化的代码

    1.参数化类型的构造函数比较啰嗦 new HashMap<String, List<String>>() 如果你调用参数化类的构造函数,那么很不幸,你必须要指定类型参数,即便上 ...

  4. in和exists哪个效率高本人测试证明

    in和exists哪个效率高本人测试证明 SQLSERVR语句 in和exists哪个效率高自己测试本人测试证明 最近很多人讨论in和exists哪个效率高,今天就自己测试一下 我使用的是客户的数据库 ...

  5. css换行和超出隐藏

    一.强制换行1 word-break: break-all; 只对英文起作用,以字母作为换行依据.2 word-wrap: break-word; 只对英文起作用,以单词作为换行依据.3 white- ...

  6. java调用Oracle存储存储过程

    数据库表和增删改的procedure参照(http://www.cnblogs.com/J-wym/p/3292913.html) 1.测试添加数据的procedure public void tes ...

  7. JavaScript –type

    JavaScript –类型之我晕 每次写博我觉得取上恬当的题目比整篇行文都难,词量有限的情况下突然想到JavaScript拾遗应该会是一个非常文艺而夺目的博文题目,但我并没有急着使用,经验告诉我应该 ...

  8. 模块化与MVC

    [javascript激增的思考02]模块化与MVC 前言 之前我们遇到了这么一个项目,也就是我们昨天提到的,有很多的小窗口的,昨天说的太抽象了,今天我们再来理一理什么是小窗口(后面点说下),当时由于 ...

  9. VMwarevSphere 服务器虚拟化之二十九 桌面虚拟化之安装View副本服务器

    VMwarevSphere 服务器虚拟化之二十九  桌面虚拟化之安装View副本服务器 VMware View中高可用性可是一个必须要考虑的问题.在整个虚拟桌面环境中View Connection S ...

  10. mongodb两次被黑后......

    先说说事情的经过...... 2017年1月8号星期天,在家翻头条无意中看到一条新闻说很多用户的mongodb被黑了,数据都被删了.当时想着公司的爬虫用的也是mongodb做存储,应该不会被黑吧,不可 ...