2014-11-14 83 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