设为首页 收藏本站
查看: 853|回复: 0

[经验分享] PHP 异步调用 后台调用 持续执行 断开连接/浏览器

[复制链接]

尚未签到

发表于 2017-4-11 10:33:05 | 显示全部楼层 |阅读模式
  标题很怪,因为我也不知道怎样用一句简短的话来概括下面这部分内容。只是希望各位 PHP 的开发者们更容易通过搜索引擎搜到这篇介绍。
  这回的核心内容就是围绕 ignore_user_abort 这个函数展开的。
  做  Web 开发的人都知道,浏览器和服务器之间是通过 HTTP 协议进行连接通讯的。这是一种基于请求和响应模型的协议。浏览器通过 URL 向某台服务器发起请求(Request),Web 服务器接收到请求,执行一段程序,然后做出响应(Response),也就是一段字符串,这个字符串符合 HTTP 协议的格式,有 HEAD 和 BODY 两部分。
  这其中有一个问题,Web  服务器执行一段程序,可能几毫秒就完成,也可能几分钟都完不成。如果程序执行缓慢,用户可能没有耐心等下去,就关闭浏览器了。这个时候,服务器会接收到连接状态改变的通知,因为 HTTP  是最上层的协议,下面还有一层 TCP 协议,TCP  会知道连接中断。连接一断,服务端的程序会立即停止执行。
  现在说到问题的关键了,服务端的程序立即停止执行,如果这个程序只是读取信息的还好说,停了就不读了呗。万一是一个写入的程序呢?比如,用户提交一段文本,也许服务端的设计比较复杂,需要同时更新好几个表,但由于某些原因,例如其中一个表被其他进程锁定,那么这个程序就会一直等待,这个时候用户要是关闭浏览器,那程序就不等了,直接退出了。结果就是这条信息保存不完整。
  举个具体的例子,用户提交的文本需要写到 A、B、C、D 四个表里,写入 A、B 两个表可能 0.1 毫秒就完成了,但 C 表被另一个进程锁定,那当前进程就得一直等,这时用户关闭浏览器,当前进程退出,那么,就会造成一种状况,A、B 表里有新的内容,而 C、D 表里没有这条内容,产生了严重的数据一致性的问题!
  虽然,利用数据库的事务,可以使状态回滚,但结果就是用户的本次提交无效。
  我希望的是,只要用户提交了,就要成功保存,也许遇到意外情况导致执行时间过长,但用户关闭浏览器也没关系。
  于是,我找到了 ignore_user_abort 这个函数。
  当调用 ignore_user_abort(1) 时, 就设定了忽略用户退出这个标志位,也就是不管怎样,也要把程序执行到底,除非在程序中调用了 exit。
  其实,还有另一个函数,register_shutdown_function,它可以注册一个函数或方法,在程序退出的时候调用,有些类似于 javascript 里面的 onunload 和 onbeforeunload 事件。
  我这里引用了 中文版PHP手册的相关内容:
  章 40. 连接处理
注意: 以下内容对 PHP 3.0.7 及更高版本适用。
  在 PHP 内部,系统维护着连接状态,其状态有三种可能的情况:
  0 - NORMAL(正常)
  1 - ABORTED(异常退出)
  2 - TIMEOUT(超时)
  当 PHP 脚本正常地运行 NORMAL 状态时,连接为有效。当远程客户端中断连接时,ABORTED 状态的标记将会被打开。远程客户端连接的中断通常是由用户点击 STOP 按钮导致的。当连接时间超过 PHP 的时限(请参阅 set_time_limit() 函数)时,TIMEOUT 状态的标记将被打开。
  可以决定脚本是否需要在客户端中断连接时退出。有时候让脚本完整地运行会带来很多方便,即使没有远程浏览器接受脚本的输出。默认的情况是当远程客户端连接中断时脚本将会退出。该处理过程可由 php.ini 的 ignore_user_abort 或由 Apache .conf 设置中对应的“php_value ignore_user_abort”以及 ignore_user_abort() 函数来控制。如果没有告诉 PHP 忽略用户的中断,脚本将会被中断,除非通过 register_shutdown_function() 设置了关闭触发函数。通过该关闭触发函数,当远程用户点击 STOP 按钮后,脚本再次尝试输出数据时,PHP 将会检测到连接已被中断,并调用关闭触发函数。
  脚本也有可能被内置的脚本计时器中断。默认的超时限制为 30 秒。这个值可以通过设置 php.ini 的 max_execution_time 或 Apache .conf 设置中对应的“php_value max_execution_time”参数或者 set_time_limit() 函数来更改。当计数器超时的时候,脚本将会类似于以上连接中断的情况退出,先前被注册过的关闭触发函数也将在这时被执行。在该关闭触发函数中,可以通过调用 connection_status() 函数来检查超时是否导致关闭触发函数被调用。如果超时导致了关闭触发函数的调用,该函数将返回 2。
  需要注意的一点是 ABORTED 和 TIMEOUT 状态可以同时有效。这在告诉 PHP 忽略用户的退出操作时是可能的。PHP 将仍然注意用户已经中断了连接但脚本仍然在运行的情况。如果到了运行的时间限制,脚本将被退出,设置过的关闭触发函数也将被执行。在这时会发现函数 connection_status() 返回 3。
  PHP 的官方网站在线文档有英文原版说明,下面还有一些用户的反馈,也很有价值,这里是链接:
  http://www.php.net/manual/en/features.connection-handling.php
  转自:http://www.leakon.com/archives/22

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-363311-1-1.html 上篇帖子: 在php中的变量和函数名前加&符号的意思 下篇帖子: Re: [zt]PHP 會被 Ruby 殺死嗎?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表