【问题标题】:PHP script with Foreach Loop running with cron - takes too long - how to do it faster使用 cron 运行 Foreach 循环的 PHP 脚本 - 耗时太长 - 如何更快地完成
【发布时间】:2017-02-21 01:49:01
【问题描述】:

我正在尝试使用 PHP 创建一个网站监控 webapp。要监控的网站的 URL 存储在 MySQL 表中。每分钟都会通过 cron 运行一个脚本 - 它遍历所有网站和 foreach URL,它使用 CURL 访问该站点并使用 CURLINFO_HTTP_CODE 获取 HTTP 代码 - 如果网站已启动,则返回 true,否则返回 false。

脚本运行正常 - 运行一两个网站需要几毫秒,但运行 20 个网站平均需要 2-15 秒。我可以看到,当添加更多站点时,这会导致问题 - 理想情况下,我需要监控数千个站点,并且用户能够添加自己的站点。

当用户添加要监视的站点时,我考虑过为每个 URL 添加单独的 cron 和文件 - 但是我不知道如何去做,我可以预见一些问题,因为我在共享服务器上工作.

那么我应该怎么做呢,或者有没有更好的方法我没有想到?

<?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


       }
}

【问题讨论】:

  • it uses CURL to visit the site and fetch the HTTP code - it returns true if the website is up and false if not 为什么不只卷曲标题并检查 http-status-code 而不是获取页面的全部内容?
  • 为什么不用update 和monitors 一次性包含所有新值,而不是执行多 sql 查询?
  • 你为什么不看看你可以同时做请求的多卷曲
  • @JustOnUnderMillions 说了什么
  • 我只在标题上使用 curl - 道歉并编辑了问题以使其更清楚。我将研究 multi curl 同时发出请求 - 谢谢@frz3993。

标签: php performance cron


【解决方案1】:

并行运行请求

PHP 在并行任务方面通常不那么出色,但它肯定是可能的。简而言之,HTTP 请求是一项非常缓慢的任务——在您的服务器和远程服务器之间有很多来回。 PHP 通常被设计为 sequential - 这意味着它一次只做一件事。因此,它最终会浪费大量时间等待远程服务器响应,一次一个。

  • 发送一个请求
  • 等很久
  • 发送一个请求
  • 等很久
  • 等等!

您需要做的是确保一起发送大量请求,然后同时等待它们。幸运的是,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。

【讨论】:

  • 为避免您的 initcwnd 崩溃,您确实应该调整批处理的大小(少于 20 个请求)。并为请求设置时间限制。
  • 谢谢 - 这是一个很大的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
  • 2017-11-06
  • 2013-07-12
  • 2012-06-27
  • 1970-01-01
相关资源
最近更新 更多