производительность — скрипт PHP с циклом Foreach, работающим с cron — занимает слишком много времени — как сделать это быстрее

Я пытаюсь создать веб-приложение для мониторинга веб-сайтов с помощью PHP. URL-адреса отслеживаемых веб-сайтов хранятся в таблице MySQL. Скрипт запускается каждую минуту через cron — он проходит по всем веб-сайтам и для каждого URL-адреса использует CURL для посещения сайта и CURLINFO_HTTP_CODE для получения HTTP-кода — он возвращает значение true, если сайт работает, и значение false, если нет.

Сценарий работает нормально — для одного или двух веб-сайтов требуется миллисекунды, но для 20 сайтов в среднем требуется 2-15 секунд. Я вижу, что это приведет к проблемам при добавлении большего количества сайтов — в идеале мне нужно, чтобы отслеживались тысячи сайтов и пользователи могли добавлять свои собственные сайты.

Я думал об отдельных кронах и файлах, добавляемых для каждого URL, когда пользователь добавляет сайт для мониторинга — однако я не уверен, как это сделать, и могу предвидеть некоторые проблемы, так как я работаю на общем сервере.

Так, как я должен идти об этом или есть лучший способ, о котором я не думал?

<?php

function visit($url) {
// VISITS WEBSITE - RETURNS TRUE IF SITE UP, FALSE IF DOWN
}

// GETS THE MONITOR DETAILS FROM DATABASE
$monitor = new Table($monitorInstance);
$all_monitors = $monitor->get('monitors');
$monitors = $monitor->tableData();

//LOOP THROUGH ALL MONITORS
foreach ($monitors as $monitor1) {

$id = $monitor1->id; //GETS ID
$website = $monitor1->url; //GETS URL
$status = $monitor1->status; //GETS STATUS - 'up' or 'down'

// RUNS FUNCTION
if (visit($website)) {
$new_status = 'up';
} else {
$new_status = 'down';
}

// IF STATUS CHANGE UPDATE THE DATABASE
if ($new_status != $status) {

try {
//update the database with the new status
$monitor->update('monitors', $id, array(
'status' => $new_status,
));

} catch(Exception $e) { //catch exceptions
die($e->getMessage());
}// ALSO SEND EMAIL TO USER}
}

0

Решение

PHP обычно не так хорош в параллельных задачах, но, безусловно, возможно. Короче говоря, HTTP-запрос — это очень медленная задача — между вашим сервером и удаленным очень много обратной связи. PHP обычно предназначен для последовательный — это означает, что он делает одну вещь за один раз. Таким образом, это в конечном итоге тратить много времени просто ожидание ответа удаленных серверов, один за раз.

  • Отправить один запрос
  • Ждать целую вечность
  • Отправить один запрос
  • Ждать целую вечность
  • так далее!

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

Вот пример функции из этот великий пост на предмет:

<?php

function multiRequest($data, $options = array()) {

// array of curl handles
$curly = array();
// data to be returned
$result = array();

// multi handle
$mh = curl_multi_init();

// loop through $data and create curl handles
// then add them to the multi-handle
foreach ($data as $id => $d) {

$curly[$id] = curl_init();

$url = (is_array($d) && !empty($d['url'])) ? $d['url'] : $d;
curl_setopt($curly[$id], CURLOPT_URL,            $url);
curl_setopt($curly[$id], CURLOPT_HEADER,         0);
curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER, 1);

// post?
if (is_array($d)) {
if (!empty($d['post'])) {
curl_setopt($curly[$id], CURLOPT_POST,       1);
curl_setopt($curly[$id], CURLOPT_POSTFIELDS, $d['post']);
}
}

// extra options?
if (!empty($options)) {
curl_setopt_array($curly[$id], $options);
}

curl_multi_add_handle($mh, $curly[$id]);
}

// execute the handles
$running = null;
do {
curl_multi_exec($mh, $running);
} while($running > 0);// get content and remove handles
foreach($curly as $id => $c) {
$result[$id] = curl_multi_getcontent($c);
curl_multi_remove_handle($mh, $c);
}

// all done
curl_multi_close($mh);

return $result;
}

?>

Использование вышесказанного выглядит так:

<?php

// An array of all the URLs to load:
$data = array(
'https://..',
'https://..',
'https://..'
);

// Load them now:
$r = multiRequest($data);

// r contains an array of responses.
print_r($r);

?>

Есть также различные библиотеки, такие как Параллельный локон тоже.

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector