我已经对此主题进行了一些谷歌搜索,但找不到我的问题的答案。
我想要实现的是以下内容:
- 客户端对服务器中的函数进行异步调用
- 服务器在后台运行该功能(因为该功能很耗时),同时客户端没有挂起
- 客户端不断调用服务器请求后台作业的状态
你能给我一些解决我问题的建议吗?
非常感谢!^-^
我已经对此主题进行了一些谷歌搜索,但找不到我的问题的答案。
我想要实现的是以下内容:
你能给我一些解决我问题的建议吗?
非常感谢!^-^
您没有指定异步调用的语言,但我假设两端都是 PHP。我认为最优雅的方式是这样的:
HTML 页面加载,为操作定义一个随机键(例如,使用rand()
或已经可用的会话 ID [请注意,虽然同一个用户可能会启动两个操作])
HTML 页面使 Ajax 调用 PHP 脚本start_process.php
start_process.php
执行exec /path/to/scriptname.php
以启动进程;有关如何在后台启动进程的建议,请参阅用户贡献的注释。exec()
哪一个适合您,主要取决于您的操作系统。
long_process.php
经常将其状态写入状态文件,以您的 Ajax 页面生成的随机密钥命名
HTML页面频繁调用show_status.php
,读取状态文件,并返回进度。
有一个长期运行的 php 进程的谷歌(请注意,关于该主题有很多不好的建议 - 包括 Pekka 提到的注释 - 这将在 Microsoft 上工作,但在其他任何事情上都会以不可预测的方式失败)。
您可以开发一个通过套接字响应请求的服务(您的客户端将使用 fsockopen 进行连接) - 实现这一点的一些简单方法是使用 Aleksey Zapparov 的套接字服务器(http://www.phpclasses.org/browse/package /5758.html)处理通过套接字传入的请求,但是由于它作为单个线程运行,因此它可能不太适合需要大量处理的东西。或者,如果您使用的是非 Microsoft 系统,那么您可以将脚本挂在 [x]inetd 上,但是,您需要做一些巧妙的事情来防止它在客户端断开连接时终止。
为了在客户端断开连接后保持运行,PHP 代码必须从独立的 PHP 可执行文件(而不是通过 Web 服务器)运行 在新的进程组中生成一个进程(参见 posix_setsid() 和 pcntl_fork())。为了使客户端能够返回并检查进度,实现此目的的最简单方法是将服务器配置为将其状态写入客户端可以读取的位置。
C。
根据定义,所有 Ajax 调用都是异步的。
您可以(尽管不是严格必要的步骤)使用 AJAX 来实例化调用,然后脚本可以创建对共享内存中后台作业状态的引用(甚至是 SQL 表中的临时条目,甚至是临时文件),以唯一作业 ID 的形式。
然后,该脚本可以启动您的后台进程并立即将作业 ID 返回给客户端。
然后客户端可以重复调用服务器(例如通过另一个 AJAX 接口)来查询作业的状态,例如“进行中”、“完成”。
如果要执行的后台进程本身是用 PHP 编写的(例如命令行 PHP 脚本),那么您可以将作业 ID 传递给它,它可以将有意义的进度更新提供回客户端(通过写入相同的共享内存区域,或数据库表)。
如果要执行的进程本身不是用 PHP 编写的,那么我建议将其包装在命令行 PHP 脚本中,以便它可以监视正在执行的进程何时完成运行(并检查输出以查看是否成功)并更新状态适当地输入该任务。
注意:为此使用共享内存是最佳做法,但例如,如果您使用共享主机,则可能不可用。不要忘记你想要清理旧状态条目的方法,所以我会为每个条目存储“started_on”/“completed_on”时间戳值,并让它删除陈旧数据的条目(例如,完成时间戳为超过 X 分钟 - 理想情况下,它还会检查一段时间前开始但从未标记为已完成的作业并发出警报)。