为什么此代码会导致服务器上的高负载平均值?

时间:2021-04-29 02:14:38

The code below sends a msg when a value, obtained from a not so stable API, is within a certain range.

当从不太稳定的API获得的值在某个范围内时,下面的代码发送一个msg。

This code causes the load average, but not the CPU usage, to go up, likely due to high I/O wait.

此代码导致负载平均值,而不是CPU使用率,可能是由于高I / O等待。

CentOS 6.5
Kernel 2.6.32-431.11.2.el6.x86_64
Apache 2.2.15
PHP 5.3.3 (mod_fcgid/2.3.7)

> cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq]

The code had the same problematic effect on both dedicated hardware and on the cloud (both cases as a VM on KVM/Virtio).

代码在专用硬件和云上都有相同的问题影响(两种情况都是作为KVM / Virtio上的VM)。

What could be done to keep this code from *causing the processor to wait on instruction completion before processing new instructions**? I understand that lowering the timeout doesn't really solve the problem, only diminishes its impact.

在处理新指令之前,可以采取哪些措施来防止处理器等待指令完成?我知道降低超时并不能真正解决问题,只会减少其影响。

*this is my understanding why this code causes load average to go up.

*这是我理解为什么这段代码导致负载平均值上升。

<?php

$min = '1';
$last_min = '1';

if (!empty($_GET['min'])) {
    $min = $_GET['min'];
} else {
    $min = false;
}

$ctx=stream_context_create(array('http'=>
    array(
        'timeout' => 10 // seconds timeout
    )
));

$json = file_get_contents('https://www.domain.com/api/ticker/',false,$ctx);

if (!empty($json )) {
    echo($json);
    if (@file_get_contents('log.txt')) {
        if (quote_changed($json)) {
            file_put_contents('log.txt', $json, FILE_APPEND);
        }
    } else {
            file_put_contents('log.txt', $json);
        }

    $obj = json_decode($json,true);
    $last = $obj['ticker']['last'];
    if (is_numeric($last)) {
        $last = (int)$last;
        $last_min = @file_get_contents('last_min.txt');
        $notified = @file_get_contents('notified.txt');
        if ($notified === false) {
            $notified = 'false';
            #echo "no notify file\n";
        }
        if (($last_min === false) || (($min) && ($last_min <> $min))) {
            $last_min = 1;
            $notified = 'false';
            file_put_contents('last_min.txt', $min);
            #echo "no min file or diff min\n";
        }
        #echo ('notified='.$notified.'\n');

        if (($last >= $min) && ($notified=='false')) {
            #$url = ('http://otherdomain.com/nexmo/sendmsg.php' . '?name=blah' . $last);
            #file_get_contents($url);
            #switch to SMS when going abroad and plugin new number when available
            mail("8885551212@mail.net","Blah at".$last,"","From: gaia@domain.com\n");
            file_put_contents('notified.txt', 'true');
            #echo "msg sent\n";
            } elseif (($last < $min) && ($notified=='true')) {
                    file_put_contents('notified.txt', 'false');
                    #echo "not sent\n";
        }           
    }
}

function quote_changed($current) {
    $previous = tailCustom('log.txt');
    #echo ('previous='.$previous);
    if ($previous === (trim($current))) {
        return 0;
    } else {
        return 1; 
    }
}

function tailCustom($filepath, $lines = 1, $adaptive = true) {

        // Open file
        $f = @fopen($filepath, "rb");
        if ($f === false) return false;

        // Sets buffer size
        if (!$adaptive) $buffer = 4096;
        else $buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096));

        // Jump to last character
        fseek($f, -1, SEEK_END);

        // Read it and adjust line number if necessary
        // (Otherwise the result would be wrong if file doesn't end with a blank line)
        if (fread($f, 1) != "\n") $lines -= 1;

        // Start reading
        $output = '';
        $chunk = '';

        // While we would like more
        while (ftell($f) > 0 && $lines >= 0) {

            // Figure out how far back we should jump
            $seek = min(ftell($f), $buffer);

            // Do the jump (backwards, relative to where we are)
            fseek($f, -$seek, SEEK_CUR);

            // Read a chunk and prepend it to our output
            $output = ($chunk = fread($f, $seek)) . $output;

            // Jump back to where we started reading
            fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);

            // Decrease our line counter
            $lines -= substr_count($chunk, "\n");

        }

        // While we have too many lines
        // (Because of buffer size we might have read too many)
        while ($lines++ < 0) {

            // Find first newline and remove all text before that
            $output = substr($output, strpos($output, "\n") + 1);

        }

        // Close file and return
        fclose($f);
        return trim($output);

}

?>

1 个解决方案

#1


1  

Move the data into a database or if that's not an option, cache the unstable file into your server locally so you don't have to hit the external provider every time.

将数据移动到数据库中,或者如果这不是一个选项,请将不稳定文件缓存到本地服务器中,这样您就不必每次都访问外部提供程序。

If neither of those are an option, it seems to me that the people providing the API need to improve their performance, you can verify this by just benchmarking how many milliseconds each hit takes through Firebug.

如果这些都不是一个选项,在我看来,提供API的人需要提高他们的性能,你可以通过对每次点击通过Firebug进行多少毫秒的基准测试来验证这一点。

#1


1  

Move the data into a database or if that's not an option, cache the unstable file into your server locally so you don't have to hit the external provider every time.

将数据移动到数据库中,或者如果这不是一个选项,请将不稳定文件缓存到本地服务器中,这样您就不必每次都访问外部提供程序。

If neither of those are an option, it seems to me that the people providing the API need to improve their performance, you can verify this by just benchmarking how many milliseconds each hit takes through Firebug.

如果这些都不是一个选项,在我看来,提供API的人需要提高他们的性能,你可以通过对每次点击通过Firebug进行多少毫秒的基准测试来验证这一点。