`
mengdejun
  • 浏览: 408080 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

PHP 异步调用 后台调用 持续执行 断开连接/浏览器

    博客分类:
  • Php
阅读更多

标题很怪,因为我也不知道怎样用一句简短的话来概括下面这部分内容。只是希望各位 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

分享到:
评论

相关推荐

    asp.net异步调用后台方法提交

    ### ASP.NET 异步调用后台方法提交 在ASP.NET开发中,为了提升用户体验和页面响应速度,异步调用后台方法是一种常见的技术手段。本文将详细介绍如何在ASP.NET中实现异步调用后台方法,并解释相关的代码实现细节。 ...

    .net异步调用后台函数

    在.NET框架中,异步调用后台函数是提高应用程序性能和用户体验的重要技术。它使得前端UI可以在等待后台处理任务时,不被阻塞,从而实现无刷新调用。以下是关于这个主题的详细解释: 1. **异步编程基础**: 异步...

    Labview异步调用示例

    在这个“Labview异步调用示例”中,我们将深入探讨LabVIEW如何实现异步编程,这是一种允许程序在等待某个操作完成时继续执行其他任务的技术。 异步调用在LabVIEW中通常涉及事件结构、多线程和回调函数等概念。首先...

    WebSerices异步调用方法总结

    WebServices 异步调用方法总结 WebService 异步调用是指在客户端和服务器端之间进行异步数据交换的过程。异步调用可以提高系统的性能和可扩展性,实现高效的数据交换。下面是 WebService 异步调用的实现方法总结: ...

    LabVIEW中异步调用+可重入VI设置

    例如,你可以创建一个可重入的后台处理VI,当用户界面触发一个异步事件时,该VI会被调用执行,同时用户界面可以继续接收和处理其他输入。这样,即使后台任务需要较长时间,也不会影响到用户界面的响应速度。 在...

    ORACLE的存储过程的异步调用

    本文讨论了 ORACLE 存储过程的异步调用方法,旨在解决客户端长时间等待存储过程执行的问题。主要思路是使用 DBMS_JOB 包将主处理存储过程作为任务提交到任务队列中,并通过 DBMS_PIPE 包将处理情况放在管道中,最后...

    Labview2015多线程异步调用工程

    在“Labview2015多线程异步调用工程”中,我们探讨的核心是利用多线程和异步调用来提高程序执行效率和并发能力。这个工程的目的是让主线程能持续快速地进行轮询,同时多个子线程可以并行处理耗时的任务,从而优化...

    异步调用流程图

    3. **执行操作**:异步任务在后台执行,可能涉及到I/O操作、数据库查询或其他耗时的操作。 4. **处理结果**:当异步任务完成,系统会将结果保存到一个数据结构中,并触发一个通知机制(如事件、回调函数或Promise链...

    C#实现异步调用外部程序

    在C#编程中,异步调用外部程序是一种常见的需求,尤其在处理耗时操作或者不希望阻塞主线程执行的情况下。本篇文章将深入探讨如何使用C#来实现这一功能,以及相关的知识点。 首先,我们需要了解异步编程的基本概念。...

    Java异步调用转同步方法实例详解

    异步调用是一种非阻塞的调用方式,调用方在调用过程中,不直接等待返回结果,而是执行其他任务,结果返回形式通常为回调函数。SYNC调用是指调用方在调用过程中,持续等待返回结果。Java中将异步调用转换为同步调用有...

    Java多线程实现异步调用实例

    在Java编程中,多线程和异步调用是提高应用程序性能和响应能力的重要手段。在本实例中,我们将深入探讨如何使用Java实现多线程以实现异步调用,并理解其背后的机制。 首先,多线程允许一个程序同时执行多个任务。在...

    ICE异步调用Demo源码

    这个“ICE异步调用Demo源码”是针对ICE框架的一个示例,展示了如何在C++环境中实现异步调用功能,特别是 adm 和 ami 函数的调用与异步分发。以下将详细解析这个Demo中的关键知识点: 1. **ICE框架**:ICE由ZeroC...

    异步调用03-轮询异步调用是否完成-c#

    可以使用由BeginInvoke方法返回的IAsyncResult的IsCompleted属性来发现...轮询完成允许调用线程在异步调用在线程池线程上执行时继续执行。 下面的代码说明了如何使用这种方法来进行异步调用,并获得异步方法的结果:

    异步调用实例01-EndInvoke-c#

    异步执行方法的最简单的方式是通过调用委托的BeginInvoke方法来开始执行方法,在主线程上执行一些工作,然后调用委托的EndInvoke方法。EndInvoke可能会阻止调用线程,因为它直到异步调用完成之后才返回。这种技术...

    Winform界面异步调用

    异步调用允许我们把耗时操作放在后台线程执行,而UI线程则继续处理用户交互。在.NET Framework中,可以使用多种方式实现Winform界面的异步调用: 1. **BackgroundWorker组件**:这是.NET Framework提供的一种简单...

    AsyncCalls(异步调用函数)

    1. **异步方法调用**:异步调用函数允许你将一个方法的调用包装成一个异步任务,然后在后台线程执行。这样,主线程可以继续处理其他任务,而不会被长时间运行的操作阻塞。 2. **事件处理**:在异步操作完成后,通常...

    Struts2之异步调用机制详解案例struts014

    异步调用的基本概念是,客户端(通常是Web浏览器)发起一个请求,服务器不立即返回结果,而是启动一个后台线程来处理请求,然后立即响应客户端,告知其请求已被接收并正在处理。之后,客户端可以通过Ajax...

    利用RMI异步调用

    在本主题“利用RMI异步调用”中,我们将探讨如何利用RMI实现异步通信,以提高系统性能和响应速度。 1. **RMI基本概念**: - **远程接口**:定义了客户端和服务器之间交互的API,这些接口的方法将在服务器端执行。 ...

    Visual C++源代码 102 如何异步调用Web Service程序

    Visual C++源代码 102 如何异步调用Web Service程序Visual C++源代码 102 如何异步调用Web Service程序Visual C++源代码 102 如何异步调用Web Service程序Visual C++源代码 102 如何异步调用Web Service程序Visual ...

    异步调用(MGI).zip

    异步调用(MGI)在LabVIEW编程中是一个重要的概念,它涉及到程序执行的并发性和效率优化。在计算机科学中,异步调用是指一个函数或过程在启动后不立即等待其完成,而是继续执行其他任务,直到该函数或过程的结果被...

Global site tag (gtag.js) - Google Analytics