这两天弄个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. 【CSS】圆角阴影边框CSS

    .someClassName { width:300px; display: inline-block; padding: 5px 10px 6px; text-decoration: none; b ...

  2. 可编辑DIV (contenteditable="true") 在鼠标光标处插入图片或者文字

    近期需开发一个DIV做的编辑器,插入表情图片可直接预览效果,仔细参考了下百度贴吧的过滤粘贴过来文件的THML代码,自己整理了下.写出来只是和大家分享下,我自己也不大懂,经过努力,幸好搞定. 蛋疼的事情 ...

  3. asp.net的ajax以及json

    asp.net的ajax以及json 来现在这家公司以前,从未接触过webform,以前在学校做的项目是php,java以及asp.net mvc的,当时asp.net mvc用的是razor引擎,所 ...

  4. ngx-push-stream模块源码学习(五)——内存清理

    1.定时器         采用nginx自身的定时器管理机制,具体细节待学习过nginx源码后加以补充 2.channel的生成周期 (0).初始(诞生)         发布.订阅均有可能产生ch ...

  5. TOGAF架构开发方法(ADM)之迁移规划阶段

    TOGAF架构开发方法(ADM)之迁移规划阶段 1.8 迁移规划(Migration Planning) 企业架构开发方法各阶段——迁移规划 1.8.1 目标 本阶段的目标是: 确保实施和迁移规划与企 ...

  6. Servlet部署描述文件(web.xml)

    最近看了下配置文件(Deployment Descriptor:简称DD),又称部署描述文件,下面详细介绍下该文件的组成和作用: 一.<web-app>有四个属性: 1.xmlns:申明了 ...

  7. Jenkins+PMD构建自动化静态代码检测

    前言:软件缺陷是不可避免的,要尽量减少错误并提高软件质量,主要有两在类技术,即缺陷预防和缺陷检测 缺陷预防包括编写更好的设计规范.实施代码审核制度.运行代码静态分析工具.运行单元测试等 PMD是一种开 ...

  8. zoj 1152 A Mathematical Curiosity

    方法:枚举 做这道题,在第十行的位置WA了很多次,(n || m)不能写成(n + m),m可能是负数,一直没注意到,导致不停的WA....... #include <stdio.h> i ...

  9. Oracle笔记(六) 多表查询

    最近看了李兴华的oracle视频,这是网上别人做的笔记非常细致,分享给大家,第六篇 原创地址:http://www.cnblogs.com/mchina/archive/2012/09/07/2651 ...

  10. android sqlite使用之模糊查询数据库数据的三种方式

    android应用开发中常常需要记录一下数据,而在查询的时候如何实现模糊查询呢?很少有文章来做这样的介绍,所以这里简单的介绍下三种sqlite的模糊查询方式,直接上代码把: package com.e ...