我正在尝试使用PHP创建一个监控webapp的网站。要监视的网站的URL存储在MySQL表中。脚本每分钟通过cron运行 - 它遍历所有网站和foreach URL,它使用CURL访问网站,CURLINFO_HTTP_CODE获取HTTP代码 - 如果网站已启动则返回true,否则返回false。
脚本工作正常 - 有一个或两个网站需要几毫秒才能运行,但有20个网站平均需要2-15秒才能运行。我可以看到,当添加更多网站时,这会导致问题 - 理想情况下,我需要监控数千个网站,用户才能添加自己的网站。
当用户添加要监控的网站时,我已经考虑过为每个网址添加单独的crons和文件 - 但是我不知道如何去做,我可以预见到一些问题,因为我正在努力共享服务器。
那么我应该如何解决这个问题,还是有一种我没有想过的更好的方法?
<?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 :(得分:0)
PHP在并行任务方面通常不是很好,但它肯定是可能的。简而言之,HTTP请求是一项非常缓慢的任务 - 在您的服务器和远程服务器之间有很多来回。 PHP通常被设计为顺序 - 这意味着它一次只做一件事。因此,它最终会浪费很多时间,只需等待远程服务器响应,一次一个。
您要做的是确保一起发出大量请求,然后同时等待它们。幸运的是,PHP提供multi curl来做到这一点。
以下是this great post关于主题的示例函数:
<?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);
?>
还有各种类似Parallel Curl的库。