PHP 上的异步方法

Asynchronous methods on Php

本文关键字:异步方法 PHP      更新时间:2023-09-26

我正在通过curl(大约43MB)在PHP上下载一个大的XML文件,然后处理该文件,验证数据并插入数据库。问题是负载均衡器在 5 分钟后停止向用户发送响应,PHP 脚本大约需要 20 分钟。我想并行运行两个PHP脚本。一个在服务器上创建一个空文件,下载并处理 xml 文件,最后删除空文件。另一个 PHP 脚本每 15 秒运行一次,并检查空文件是否仍退出。我在并行运行这两个脚本时遇到问题。这是我的代码:

$(document).ready(function() {
$(document).on("click", ".clickMe", function () {
    var download = $.ajax({
        async: true,
        url: "/staff/import.php",
        type: "post",
        data: { getFile: true },
        dataType: "json",
        success: function (data) {
        }
    });
    var serverStatus = true;
    while (serverStatus === true) {
        var checkDownload = $.ajax({
            async: false,
            url: "/staff/checkDownload.php",
            type: "post",
            dataType: "json",
            data: { checkDownload: true },
            success: function (returndata) {
                if (returndata === false) {
                    serverStatus = false;
                }
            }
        });
    }
});

});

PHP 卷曲下载:

<?php
session_write_close();
touch(getcwd() . "downloading");
$curl = curl_init(); //
$post = array("uploadfile"=>"@" . getcwd() . "/tmp.xml");
curl_setopt($curl, CURLOPT_URL, "sftp://<host>/bigFile.xml");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_USERAGENT,"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)");
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
curl_setopt($curl, CURLOPT_USERPWD, "<userName>:<password>");
file_put_contents(getcwd() . "/tmp.xml", curl_exec($curl));
curl_close($curl);
unlink(getcwd() . "downloading");
// process xml file
// insert into database

PHP检查下载:

<?php
$return = file_exists(getcwd() . "/tmp/downloading");
echo json_encode(true);

为了使两个PHP脚本并行运行,我读到我需要禁用会话[session_write_close();]但仍然一个等待另一个完成。如果我在代码(Javascript或PHP)上做错了什么,任何人都可以告诉我任何信息,或者知道任何其他方法可以做到这一点?谢谢

我更喜欢基于databasenohup php的解决方案

如果我没猜错,你的"更大的脚本"就是 curl 请求。所以拿这个脚本

touch(getcwd() . "downloading");
$curl = curl_init(); //
$post = array("uploadfile"=>"@" . getcwd() . "/tmp.xml"); 
curl_setopt($curl, CURLOPT_URL, "sftp://<host>/bigFile.xml);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_USERAGENT,"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)");
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
curl_setopt($curl, CURLOPT_USERPWD, "<userName>:<password>");
file_put_contents(getcwd() . "/tmp.xml", curl_exec($curl));
curl_close($curl);
unlink(getcwd() . "downloading");
// process xml file
// insert into database

旁注:

在命令行上运行时,您需要设置所有被调用文件的完整路径


并在文件开头添加一个插入语句并将其插入到您的数据库中,例如

INSERT INTO checkrun (started, done) VALUES (NOW(), 0);

在 curl_close() 之后,添加类似

UPDATE checkrun set done = 1 WHERE id = (SELECT max(id) FROM checkrun);

现在将其安全到另一个文件并将其放入服务器上任何位置的文件夹中,让我们采取/user/curlfile/curlrequest.php.

您的第一个 ajax 调用现在将转到 webroot 中的一个文件,该文件应包含一个 exec 语句,如下所示:

exec('nohup php /user/curlfile/curlrequest.php');
您的

文件现在正在运行并设置为后台,这意味着它不会影响您的其余工作(至少更少)。 nohup通常会创建一个日志文件,如果您不希望这样做,请添加

>/dev/null 2>&1 &

在您的 nohup 命令之后。


使用第二个 ajax 调用,您可以运行一个脚本,该脚本只需检查表检查运行中的max(id)if done = 0它必须继续,if done = 1 curl 请求完成并且您可以做任何您想做的事情。我会与

setTimeout();

每 15 秒或您想要的任何时间检查一次的功能。


注意:

这种数据库检查仅在您一次有一个 curl 请求时才有效,如果您有更多请求,我会在您的页面中创建一个随机字符串来执行 ajax 调用并将此字符串发送到您的文件。您可以使用getopt来执行此操作:

$options = getopt("f:");
var_dump($options);

在你的 curl 文件中并运行你的 exec 命令,如

exec('nohup php /user/curlfile/curlrequest.php -f "randomString"');

现在您可以简单地检查完成

WHERE requestId = randomString

我希望我没有忘记一些事情,但这应该以更少的痛苦来完成这项工作。