php异步调用并从后台作业获取响应

发布于 2024-08-19 13:39:20 字数 212 浏览 5 评论 0 原文

我已经对这个主题进行了一些谷歌搜索,但找不到我的问题的答案。

我想要实现的目标如下:

  1. 客户端对服务器中的函数进行异步调用,
  2. 服务器在后台运行该函数(因为该函数非常耗时),并且客户端不会同时挂起
  3. 客户端不断致电服务器请求后台作业的状态

您能给我一些解决问题的建议吗?

非常感谢! ^-^

I have done some google search on this topic and couldn't find the answer to my question.

What I want to achieve is the following:

  1. the client make an asynchronous call to a function in the server
  2. the server runs that function in the background (because that function is time consuming), and the client is not hanging in the meantime
  3. the client constantly make a call to the server requesting the status of the background job

Can you please give me some advices on resolving my issue?

Thank you very much! ^-^

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

挖鼻大婶 2024-08-26 13:39:20

您没有指定异步调用使用的语言,但我假设两端都是 PHP。
我认为最优雅的方式是这样的:

  • HTML 页面加载,定义操作的随机密钥(例如使用 rand() 或已经可用的会话 ID [请注意,尽管相同用户可以启动两个操作])

  • HTML 页面对 PHP 脚本进行 Ajax 调用 start_process.php

  • start_process.php 执行 exec /path/to/scriptname.php 启动进程;请参阅关于exec()<的用户贡献的注释< /code> 关于如何在后台启动进程的建议。哪一个适合您,主要取决于您的操作系统。

  • long_process.php 经常将其状态写入状态文件,该文件以 Ajax 页面生成的随机密钥命名

  • HTML 页面频繁调用 show_status.php 来读取状态文件并返回进度。

You are not specifying what language the asynchronous call is in, but I'm assuming PHP on both ends.
I think the most elegant way would be this:

  • HTML page loads, defines a random key for the operation (e.g. using rand() or an already available session ID [be careful though that the same user could be starting two operations])

  • HTML page makes Ajax call to PHP script to start_process.php

  • start_process.php executes exec /path/to/scriptname.php to start the process; see the User Contributed Notes on exec() on suggestions how to start a process in the background. Which one is the right for you, depends mainly on your OS.

  • long_process.php frequently writes its status into a status file, named after the random key that your Ajax page generated

  • HTML page makes frequent calls to show_status.php that reads out the status file, and returns the progress.

初见终念 2024-08-26 13:39:20

在 google 上搜索长时间运行的 php 进程(请注意,关于该主题有很多不好的建议 - 包括 Pekka 提到的注释 - 这在 Microsoft 上有效,但在其他任何地方都会以不可预测的方式失败)。

您可以开发一个通过套接字响应请求的服务(您的客户端将使用 fsockopen 进行连接) - 实现此目的的一些简单方法是使用 Aleksey Zapparov 的 Socket 服务器(http://www.phpclasses.org/browse/package/5758.html) 处理通过套接字传入的请求,但是因为这作为单个线程运行,它可能不太适合需要大量处理的事情。或者,如果您使用的是非 Microsoft 系统,那么您可以将脚本挂在 [x]inetd 上,但是,您需要做一些聪明的事情来防止它在客户端断开连接时终止。

为了在客户端断开连接后保持运行,PHP 代码必须从独立的 PHP 可执行文件运行(而不是通过网络服务器)在新的进程组中生成一个进程(请参阅 posix_setsid() 和 pcntl_fork())。为了使客户端能够返回并检查进度,实现此目的的最简单方法是将服务器配置为将其状态写入客户端可以读取的位置。

C.

Have a google for long running php processes (be warned that there's a lot of bad advice out there on the topic - including the note referred to by Pekka - this will work on Microsoft but will fail in unpredicatable ways on anything else).

You could develop a service which responds to requests over a socket (your client would use fsockopen to connect) - some simple ways of acheiving this would be to use Aleksey Zapparov's Socket server (http://www.phpclasses.org/browse/package/5758.html) which handles requests coming in via a socket however since this runs as a single thread it may not be very appropriate for something which requiers a lot of processing. ALternatively, if you are using a non-Microsoft system then yo could hang your script off [x]inetd however, you'll need to do some clever stuff to prevent it terminating when the client disconnects.

To keep the thing running after your client disconnects then the PHP code must be running from the standalone PHP executable (not via the webserver) Spawn a process in a new process group (see posix_setsid() and pcntl_fork()). To enable the client to come back and check on progress, the easiest way to achieve this is to configure the server to write out its status to somewhere the client can read.

C.

清风夜微凉 2024-08-26 13:39:20
  1. Ajax 调用运行方法 longRunningMethod() 并返回一个标识符(例如 id)
  2. 服务器运行该方法,并在例如共享内存中设置密钥
  3. 客户端调用 checkTask(id)
  4. 服务器在共享内存中查找密钥并检查就绪状态
    [重复 3 & 4 直到 5 完成]
  5. longRunningMethod 完成并在共享内存中将状态设置为完成。

根据定义,所有 Ajax 调用都是异步的。

  1. Ajax call run method longRunningMethod() and get back an idendifier (e.g an id)
  2. Server runs the method, and sets key in e.g. sharedmem
  3. Client calls checkTask(id)
  4. server lookup the key in sharedmem and check for ready status
    [repeat 3 & 4 until 5 is finished]
  5. longRunningMethod is finished and sets state to finished in sharedmem.

All Ajax calls are per definition asynchronous.

夏夜暖风 2024-08-26 13:39:20

您可以(尽管不是严格必要的步骤)使用 AJAX 来实例化调用,然后脚本可以在共享内存中创建对后台作业状态的引用(甚至是 SQL 表中的临时条目,甚至是临时条目)文件),以唯一的作业 ID 的形式。

然后,该脚本可以启动后台进程并立即将作业 ID 返回给客户端。

然后,客户端可以重复调用服务器(例如,通过另一个 AJAX 接口)来查询作业的状态,例如“正在进行”、“完成”。

如果要执行的后台进程本身是用 PHP 编写的(例如命令行 PHP 脚本),那么您可以将作业 ID 传递给它,它可以向客户端提供有意义的进度更新(通过写入相同的共享内存区域,或数据库表)。

如果要执行的进程本身不是用 PHP 编写的,那么我建议将其包装在命令行 PHP 脚本中,以便它可以监视正在执行的进程何时完成运行(并检查输出以查看是否成功)并更新状态适当地进入该任务。

注意:为此使用共享内存是最佳实践,但例如,如果您使用共享托管,则可能不可用。不要忘记您希望有一种方法来清理旧的状态条目,因此我会为每个条目存储“started_on”/“completed_on”时间戳值,并让它删除陈旧数据的条目(例如,具有completed_on时间戳的条目)超过 X 分钟 - 并且理想情况下,还会检查一段时间前开始但从未标记为已完成的作业并发出有关它们的警报)。

You could (although not a strictly necessary step) use AJAX to instantiate the call, and the script could then create a reference to the status of the background job in shared memory (or even a temporary entry in an SQL table, or even a temp file), in the form of a unique job id.

The script could then kick off your background process and immediately return the job ID to the client.

The client could then call the server repeatedly (via another AJAX interface, for example) to query the status of the job, e.g. "in progress", "complete".

If the background process to be executed is itself written in PHP (e.g. a command line PHP script) then you could pass the job id to it and it could provide meaningful progress updates back to the client (by writing to the same shared memory area, or database table).

If the process to executed it's not itself written in PHP then I suggest wrapping it in a command line PHP script so that it can monitor when the process being executed has finished running (and check the output to see if was successful) and update the status entry for that task appropriately.

Note: Using shared memory for this is best practice, but may not be available if you are using shared hosting, for example. Don't forget you want to have a means to clean up old status entries, so I would store "started_on"/"completed_on" timestamps values for each one, and have it delete entries for stale data (e.g. that have a completed_on timestamp of more than X minutes - and, ideally, that also checks for jobs that started some time ago but were never marked as completed and raises an alert about them).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文