Обработка больших объемов данных в PHP без тайм-аута браузера - PullRequest
13 голосов
/ 04 апреля 2011

У меня есть набор мобильных номеров, около 50 000. Я пытаюсь обработать и отправить смс на эти номера с помощью стороннего API, но браузер зависнет на несколько минут. Я ищу лучший вариант.

Обработка данных включает проверку типа мобильного номера (например, CDMA), присвоение уникальных идентификаторов всем номерам для дальнейших ссылок, проверку уникальных тарифов сети / страны и т. Д.

Я думал о постановке в очередь данных в базе данных и использовании cron для отправки около 5 тыс. Пакетов партиями каждую минуту, но это займет время, если будет много сообщений. Какие у меня есть другие варианты?

Я использую Codeigniter 2 на сервере XAMPP.

Ответы [ 4 ]

37 голосов
/ 04 апреля 2011

Я бы написал два сценария:

Файл index.php:

<iframe src="job.php" frameborder="0" scrolling="no" width="1" height="1"></iframe>
<script type="text/javascript">
    function progress(percent){
        document.getElementById('done').innerHTML=percent+'%';
    }
</script><div id="done">0%</div>

Файл job.php:

set_time_limit(0);                   // ignore php timeout
ignore_user_abort(true);             // keep on going even if user pulls the plug*
while(ob_get_level())ob_end_clean(); // remove output buffers
ob_implicit_flush(true);             // output stuff directly
// * This absolutely depends on whether you want the user to stop the process
//   or not. For example: You might create a stop button in index.php like so:
//     <a href="javascript:window.frames[0].location='';">Stop!</a>
//     <a href="javascript:window.frames[0].location='job.php';">Start</a>
// But of course, you will need that line of code commented out for this feature to work.

function progress($percent){
    echo '<script type="text/javascript">parent.progress('.$percent.');</script>';
}

$total=count($mobiles);
echo '<!DOCTYPE html><html><head></head><body>'; // webkit hotfix
foreach($mobiles as $i=>$mobile){
    // send sms
    progress($i/$total*100);
}
progress(100);
echo '</body></html>'; // webkit hotfix
1 голос
/ 04 апреля 2011

Если это не единичный тип ситуации, подумайте над созданием лучшего решения.

То, что вы в основном хотите, - это очередь, в которую может писать процесс, связанный с вашим браузером, и чем 1-Nрабочие процессы могут читать и обновлять.

Помещение работы в очередь должно быть довольно недорогим - возможно, набором простых инструкций INSERT для СУБД SQL.

Тогда у вас может быть один или два демона (или 100, распределенных по нескольким серверам).), которые читают из очереди и обрабатывают вещи.Вам нужно быть осторожным и избегать двух рабочих, выполняющих одну и ту же задачу, но это не сложно кодировать.

Итак, ваш рабочий процесс, связанный с браузером: нажмите какую-нибудь кнопку, которая вызывает кучу вещей, которыедобавить в очередь, а затем перенаправить на некоторый интерфейс «состояние очереди», где пользователь может наблюдать, как система просматривает всю свою работу.

Такая система хороша, потому что ее легко масштабировать горизонтальнопути.

РЕДАКТИРОВАТЬ: ответ Кристиана Скиберраса идет в этом направлении, за исключением того, что браузер в конечном итоге движет обе стороны (он добавляет в очередь, а затем приводит в действие рабочий процесс)

1 голос
/ 04 апреля 2011

Я предполагаю, что эти числа находятся в базе данных, если это так, вы должны добавить новый столбец с названием isSent (или как вам нравится).

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

Обработка данных включает проверку типа мобильного номера (например, CDMA), присвоение уникальных идентификаторов всем номерам для дальнейших ссылок, проверку уникальных сборов сети / страны и т. Д.

Но это по-прежнему приводит кВы возвращаетесь к тому же вопросу о том, как сделать это для 50 000 номеров одновременно.Поскольку вы упомянули задания cron, я предполагаю, что у вас есть SSH-доступ к вашему серверу, что означает, что вам не нужен браузер.Эти задания cron могут быть выполнены через командную строку следующим образом:

/ usr / bin / php /home/username/example.com/myscript.php

Моя рекомендация заключается в обработке 1000 чиселчерез каждые 10 минут через cron и сколько времени это займет, затем сохраните его в БД.Поскольку вы используете задание cron, не похоже, что это чувствительные ко времени SMS-сообщения, поэтому их можно распространять.Как только вы узнаете, сколько времени потребовалось для выполнения этого скрипта 50 раз (50 * 1000 = 50 КБ), вы можете обновить свое задание cron, чтобы оно выполнялось более / менее часто.

$time_start = microtime(true);
set_time_limit(0);

function doSendSMS($phoneNum, $msg, $blah);

$time_end = microtime(true);
$time = $time_end - $time_start;
saveTimeRequiredToSendMessagesInDB($time);

Кроме того, вы могли заметитьset_time_limit (0), это скажет PHP, чтобы не превышать тайм-аут после 30 секунд по умолчанию.Если вы можете изменить файл PHP.ini, вам не нужно вводить эту строку кода.Даже если вы можете редактировать файл PHP.ini, я все равно рекомендую не изменять эту функцию, поскольку вы можете захотеть, чтобы время ожидания других страниц истекло.

http://php.net/manual/en/function.set-time-limit.php

0 голосов
/ 04 апреля 2011

Cronjob будет вашим лучшим выбором, я не понимаю, почему это займет больше времени, чем выполнение в браузере, если ваша единственная проблема на данный момент - тайм-аут браузера.

Если вы настаиваете наделая это через браузер, тогда другое решение будет делать это, скажем, 1000, и перенаправлять на тот же скрипт, но с некоторой ссылкой на то, где он находился в последний раз в переменной $ _GET.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...