2014-11-14 39 views
0

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

$(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脚本[session_write_close();]但还是一个等到另一个完成。如果我在我的代码(Javascript或PHP)上做错了什么或者知道有其他方法来做到这一点,任何人都可以给我任何提示? 感谢

+0

我认为这取决于服务器而不是php如何执行。据我所知,Apache会一一执行此操作 - 如果我错了,请纠正我的错误......您的更大的脚本会因此“阻止”您的执行堆栈 – 2014-11-14 12:27:51

+1

如何在服务器的后台运行作业并拥有表单“队列”系统(甚至可能有进展?)。然后简单地发回一个“queueID”,当队列项目完成时(每隔N秒检查一次ajax),返回文件。 – h2ooooooo 2014-11-14 13:28:38

+1

这也是我的问题。我写了一个更长的答案。你认为有什么可以改善@ h2ooooooo,我只是写了什么来到我的脑海里... – baao 2014-11-14 13:33:16

回答

3

我宁愿基于databasenohup php

如果我得到你的权利,你的“大剧本”是卷曲的要求的解决方案。所以借这个脚本

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语句时,你需要完整路径设置为所有被调用的文件文件的开头并将其插入数据库,如

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调用现在会去你的根目录文件,该文件应包含exec声明,就像这样:

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

你的文件正在运行,设置为背景,手段它不影响你的其他工作(至少少得多)。 nohup通常会创建一个日志文件,如果你不希望这样,加

>/dev/null 2>&1 & 

您nohup命令后。


你的第二个Ajax调用,您可以运行一个脚本,简单地检查了max(id)表checkrun和,if done = 0它必须继续,if done = 1您的卷曲的请求做,你可以做任何你想要的。我会与一个

setTimeout(); 

函数检查每15秒,或任何你想要的时间。


注:

这种数据库的检查将只,如果你有一次在一个卷曲的请求,如果您有更多的我想创建在你的页面,做Ajax调用一个随机字符串并将此字符串发送到您的文件。在袅袅文件

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

和运行像

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

你exec命令现在,你可以简单地检查做

WHERE requestId = randomString 

我希望我没有:您可以通过使用getopt做到这一点不要忘记一些事情,但是这应该尽可能减轻痛苦地完成工作。

+0

谢谢。非常好的主意。我会尝试一下,我会让你知道我是如何去做这件事的。 – ivantxo 2014-11-14 22:17:37