PHP脚本滞后于我的网站

时间:2014-08-01 05:00:25

标签: php mysql cron

所以我有这个脚本(这对网站很重要),它每3-5分钟运行一次。

基本上,此脚本的作用是从API请求获取信息并使用新的API请求更新表。

问题是,它运行了很多API请求(大约500个?),因为我的表有500个条目。

正因为如此,每次运行此脚本时,我的CPU都会使用100%的限制。那我怎么能避免这种情况呢。如何单独限制此脚本的CPU使用率?

header('Content-Type: text/html; charset=UTF-8');
date_default_timezone_set('America/Los_Angeles');
echo memory_get_usage() . "\n";

$con = mysqli_connect("localhost", "***", "***", '***');
$result = mysqli_query($con,"SELECT * FROM **_streams");

while($row = mysqli_fetch_array($result)) {

    $json_array = json_decode(file_get_contents('https://api.twitch.tv/kraken/streams/'.strtolower($row['channel'])), true);
    if ($json_array['stream'] != NULL) {

        // turn them into variables to prevent outside SQL injection
        $displayname = mysqli_real_escape_string($con,$json_array['stream']['channel']['display_name']);
        $title = mysqli_real_escape_string($con,$json_array['stream']['channel']['status']);
        $game = mysqli_real_escape_string($con,$json_array['stream']['channel']['game']);
        $viewers = mysqli_real_escape_string($con,$json_array['stream']['viewers']);
        $preview = mysqli_real_escape_string($con,$json_array['stream']['preview']['medium']);
        $followers = mysqli_real_escape_string($con,$json_array['stream']['channel']['followers']);
        $date = date('m/d/Y h:i:s a', time());

        mysqli_query($con,"SET NAMES utf8mb4");
        mysqli_query($con,"UPDATE mybb_streams SET `online` = '1', `title` = '$title', `viewers` = '$viewers', `game` = '$game', `preview` = '$preview', `followers` = '$followers', `lastactive` = '$date' WHERE `channel` = '".strtolower($row['channel'])."'") or die("A MySQL error has occurred.<br />Your Query: UPDATE `streams` SET `online` = `1`, `title` = `$title`, `viewers` = `$viewers`, `game` = `$game`, `preview` = `$preview` WHERE channel = '".strtolower($row['channel'])."'<br /> Error: (" . mysqli_errno($con) . ") " . mysqli_error($con));
    }

    else {
      mysqli_query($con,"UPDATE mybb_streams SET `online` = '0', `viewers` = '0' WHERE `channel` = '".strtolower($row['channel'])."'") or die("A MySQL error has occurred.<br />Your Query: UPDATE streams SET `online` = '0', `viewers` = '0' WHERE `channel` = '".strtolower($row['channel'])."'<br /> Error: (" . mysqli_errno($con) . ") " . mysqli_error($con));
    }

}

echo memory_get_usage() . "\n"; 

?>

数据库刷新了!

4 个答案:

答案 0 :(得分:0)

我打赌它会非常慢。对于每个流,你A)向api.twitch.tv发出一个HTTP请求(php停止所有执行,直到从api返回一个响应)然后你执行两个查询。

我只是看了同样的api,如果你先打电话给https://api.twitch.tv/kraken/streams,它会给你一个我猜测的所有流的列表。

所以执行一次调用以获取所有流然后循环访问API结果并以这种方式更新数据库。

答案 1 :(得分:0)

希望我的建议会给你一些帮助。

我的建议: 如果您使用CRON Job,那么您可以使用内存限制来解决此问题

帮助完整链接:

  1. http://piwik.org/docs/setup-auto-archiving/

  2. https://www.urbaninsight.com/2011/06/06/fixing-out-of-memory-problem-for-cron-job

  3. https://serverfault.com/questions/295584/php-cli-memory-limit

  4. 示例代码:

    <?php
    if ($_SERVER['PHP_SELF'] == '/cron.php' or
        (isset($_GET['q']) and $_GET['q'] == 'admin/reports/status/run-cron')) {
      ini_set('memory_limit', '256M'); // Set higher value if needed
    }
    ?>
    

    我的另一个建议:

    您需要优化MySql Innodb Performance。

    提高SELECT操作性能的最佳方法是在查询中测试的一个或多个列上创建索引。索引条目的作用类似于表行的指针,允许查询快速确定哪些行与WHERE子句中的条件匹配,并检索这些行的其他列值。可以索引所有MySQL数据类型。

    1. http://dev.mysql.com/doc/refman/5.1/en/optimize-table.html

    2. http://dev.mysql.com/doc/refman/5.5/en/optimization-indexes.html

    3. http://www.sitepoint.com/optimizing-mysql-indexes/

    4. http://www.mysqlperformanceblog.com/2013/04/26/more-on-mysql-transaction-descriptors-optimization/

    5. http://www.mysqlperformanceblog.com/2013/09/20/innodb-performance-optimization-basics-updated/

    6. http://www.mysqlperformanceblog.com/2007/11/01/innodb-performance-optimization-basics/

答案 2 :(得分:0)

我的两分钱:

您可以使用nice,不会限制CPU使用率,但会优先考虑您的脚本:

nice -n 20 php ./streams.php

答案 3 :(得分:0)

<强> ReactPHP

也许您可以查看ReactPHP(https://github.com/reactphp/react),它提供了一种使用非阻塞请求和承诺的简便方法。

ReactPHP允许您在同一时间向您的API发送多个请求,而无需等待每个请求结束。

此页面提供了并行下载的示例:https://github.com/reactphp/react/blob/split/examples/parallel-download.php

<强>的MessageQueue

您还可以使用像RabbitMQ(http://www.rabbitmq.com/)这样的MessageQueue来请求您的API。 看看这个博客,它提供了从简单的请求系统迁移到RabbitMQ和专业人员的示例:http://knplabs.com/blog/2012/02/03/knpbundles-now-uses-rabbitmq/