使用100%cpu的php-fpm和fwrite问题

时间:2012-10-29 23:26:22

标签: nginx php

我有一个不寻常的问题,我设法找到了根。 我目前正在建立 CentOS Linux 6.3 nginx的/ 1.0.15 PHP版本5.3.18 PHP-FPM 5.3.18-1

我有一个refresh.txt文件,每当有人发布一个喊号来更新新的时间戳时就会写入该文件。我们还有JS每1秒检查一次这个时间戳的值。现在的问题是..说5个或更多的人同时写入refresh.txt文件,它将使用100%的CPU。只是写一个时间戳!!

我不知道为什么会这样做..

这是我的PHP代码。

if(!empty($rf_clear))
    $tb_send = "clear";
else
    $tb_send = time();

// Add flatfile check
$tbcheck = "refresh.txt";
    $tbsend = fopen($tbcheck, 'w');
    $tbtime = $tb_send;
fwrite($tbsend, $tbtime);
fclose($tbsend);

JS

talk_jax.open("GET", boardurl+"/talkbox/refresh.txt?nocache="+nocache);

我该如何解决这个问题或者解决这个问题呢? 任何帮助都会让我大受赞赏。

感谢。

编辑: 仍然没有解决这个问题。有没有办法限制请求? 或者有更好的方法将这一切结合在一起。

我已经尝试过APC缓存,问题在于它没有足够快地提供php文件 所以喊叫真的很慢,除非我做错了什么?

apc_store("refresh", time());

JS

talk_jax.open("GET", boardurl+"/talkbox/refresh.php?nocache="+nocache);

我也尝试过使用数据库。它同样太慢,无法提供php文件。

2 个答案:

答案 0 :(得分:3)

最好的选择是使用flock()来锁定您的文件以进行编写 - http://ar2.php.net/flock - 使用循环来实现Windows兼容性,因为flock没有阻止选项(在您的CentOS的情况,但无害)。

$max_tries = 5; // don't loop forever
$tbcheck = "refresh.txt";
$tbsend = fopen($tbcheck, 'w');
for ($try=0; $try<$max_tries, $try++){
    if (flock($tbsend, LOCK_EX, true)) {  // acquire an exclusive blocking lock
        fwrite($tbsend, $tb_send);  // write to file
        fflush($tbsend);            // flush output before releasing the lock
        flock($tbsend, LOCK_UN);    // release the lock
        break;                      // exit the loop
    }
    usleep(100);                    // sleep for 100ms if we couldn't get a lock
}
fclose($tbsend);

另一种选择是使用APCmemcached来存储锁,然后可以从其他PHP进程检查。假设你有memcached你的代码看起来像这样:

$timeout = 5; // set a cache expiration so a broken process doesn't lock forever
$key = "file_locked";
$max_tries = 5; // don't loop forever
for ($try=0; $try<$max_tries, $try++){
    // check to see if there is a lock
    if (!Memcached::get($key)){
        // not locked, so set a lock before processing
        Memcached::set($key, true, $timeout);

        // write to the file
        $tbcheck = "refresh.txt";
        $tbsend = fopen($tbcheck, 'w');
        $tbtime = $tb_send;
        fwrite($tbsend, $tbtime);
        fclose($tbsend);

        // delete the lock
        Memcached::delete($key);

        // exit the loop
        break;
    }
    // locked, pause for 100ms
    usleep(100);
}

答案 1 :(得分:1)

请考虑使用Apc apc_store('refresh', time());存储
apc_get('refresh');要撤退

yum install php-apc

此外,您甚至不必将时间存入其中 你可以存放一个柜台 apc_inc('refresher');存储
每次发生变化时都会增加 并检查js是否新值高于您之前的值。