2014-11-14 3 views
0

Я загружаю большой XML-файл на PHP через curl (около 43 МБ), затем обрабатываю этот файл, проверяя данные и вставляя их в базу данных. Проблема заключается в том, что балансировщик нагрузки перестает посылать ответ пользователю через 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 Curl Скачать:

<?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 делает это 1 на 1, насколько я знаю, - исправьте меня, если я ошибаюсь ... ваш большой скрипт для этого «блокировал» ваш стек исполнения –

+1

Как о запуске задания в фоновом режиме на сервере и в форме системы «очереди» (возможно, даже с прогрессом?). Затем просто отправьте обратно «queueID», и когда элемент очереди будет завершен (проверьте с ajax каждую N-ю секунду), верните файл. – h2ooooooo

+1

Это мое отношение к этому, тоже. Я написал для этого более длинный ответ. Вы думаете, что что-то может быть улучшено там @ h2ooooooo, я просто написал, что пришло мне в голову ... – baao

ответ

3

Я предпочел бы решение, основанное на database и nohup 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 

Sidenote:

вам необходимо установить полные пути ко всем призванным файлов при работе в командной строке


и добавить вставки заявление в начало файла и вставить его в вашу базу данных, например

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.

Ваш первый Аякса звонок теперь будет идти к файлу в вашем вебсервера, этот файл должен содержать exec заявление, например:

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

файл теперь работает и набор на фоне, средства это не влияет на остальную часть вашей работы (по крайней мере, меньше). nohup обычно создает лог-файл, если вы не хотите этого, добавьте

>/dev/null 2>&1 & 

после команды поЬира.


Со вторым АЯКС вызова, вы можете запустить скрипт, который просто проверяет таблицу checkrun для max(id) и if done = 0 он должен продолжать, if done = 1 ваш локон запрос сделан, и вы можете делать все, что вы хотите. Я бы работал с

setTimeout(); 

Функция проверки каждые 15 секунд или любое другое время.


Примечание:

Этого вид проверки базы данных будет работать только если у вас есть один запрос завитка в то время, если у вас есть больше, я бы создать случайную строку в вашей странице, которая делает Аякс звонков и отправьте эту строку в свои файлы. Вы можете сделать это с помощью getopt:

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

в вашем завитка файл и запустить команду EXEC как

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

Теперь вы можете просто проверить проделанную

WHERE requestId = randomString 

Я надеюсь, что Бесполезный «Забудь что-то, но это должно делать работу с меньшей болью.

+0

спасибо. Очень хорошая идея. Я попробую, и я дам вам знать, как я пойду с этим. – ivantxo

Смежные вопросы