3

私の Web サイトでは、30 分ごとに Cron ジョブを実行しています。これらの 30 分マークで Web サイトにアクセスしようとすると、500 内部サーバー エラーが発生するか、サイトのページの読み込みに 5 ~ 10 秒かかります。

私は Php を使用しており、私の cron ジョブは Php と MySQL を使用しています。

ウェブサイト全体が遅れないようにするにはどうすればよいですか、または遅れが少なくなるように速くするにはどうすればよいですか?

クロン:ここに画像の説明を入力

15 分ごとに実行される cron の 1 つ:

<?php
require('functions.php');

global $mysqli;

$select = $mysqli->prepare("SELECT `tkn` FROM `users` ORDER BY `dt` ASC LIMIT 0, 200");
$select->execute();
$select->bind_result($cur_token);

$tokens = array();

while($select->fetch())
{
    array_push($tokens, $cur_token);
}

foreach($tokens as $token)
{
    $api = Class::Instance($token);
    $info = $api->Users->Info();

    if(empty($info->error))
    {
        $info->data->token = $token;
        updateUser($info->data);

    } else if($info->error->code == 400) {
        $update = $mysqli->prepare("UPDATE `users` SET `active` = 0 WHERE `tkn` = ?");
        $update->bind_param('s', $token);
        $update->execute();
    }
}

?>

その他の Cron ジョブ:

<?php
require('functions.php');

global $mysqli;

$select = $mysqli->prepare("SELECT `email`, `username`, `id` FROM `users` WHERE `email` IS NOT NULL AND `email` <> '' AND `credits` < `credits_offered` AND `emailed_credits` = 0");
$select->execute();
$select->bind_result($email, $username, $id);

$users = array();

while($select->fetch())
{
    $users[] = array("id" => $id, "email" => $email, "username" => $username);
}

foreach($users as $user)
{
    $to      = $user['email'];
    $subject = '';
    $message = "";
    $headers = 'From: email@domain.com' . "\r\n" .
        'Reply-To: reply@domain.com';

    mail($to, $subject, $message, $headers);

    $update = $mysqli->prepare("UPDATE `users` SET `emailed` = 1 WHERE `id` = ?");
    $update->bind_param('i', &$user['id']);

    $update->execute();
    $update->close();
}


?>

これらの遅延を少なくする、またはまったく遅延させないようにするにはどうすればよいですか?

4

2 に答える 2

2

最初の提案は、準備呼び出しをループの外に移動することです。更新はしばらくテーブルをロックするので、操作が終了した後にのみ更新します...更新が必要なものを配列にキャッシュし、トランザクションを開始し、コミットする前にすべての更新を行います。メーリング スクリプトの更新されたコード サンプル

<?php
require('functions.php');

global $mysqli;

$select = $mysqli->prepare("SELECT `email`, `username`, `id` FROM `users` WHERE `email` IS NOT NULL AND `email` <> '' AND `credits` < `credits_offered` AND `emailed_credits` = 0");
$select->execute();
$select->bind_result($email, $username, $id);

$users = array();

while($select->fetch())
{
    $users[] = array("id" => $id, "email" => $email, "username" => $username);
}

$u = array();

foreach($users as $user)
{
    $to      = $user['email'];
    $subject = '';
    $message = "";
    $headers = 'From: email@domain.com' . "\r\n" .
        'Reply-To: reply@domain.com';

    mail($to, $subject, $message, $headers);
    $u[] = $user['id'];

}
$update = $mysqli->prepare("UPDATE `users` SET `emailed` = 1 WHERE `id` = ?");
$update->bind_param('i', &$i);
$mysqli->autocommit(false);
foreach($u as $i)
    $update->execute();
$update->close();
$mysqli->commit();

ああ、ほとんど忘れていましたが、ほとんどの mysql ストレージ エンジンはかなりばかげています。トランザクションをサポートしている InnoDB を必ず使用してください。または、「愚かな」ストレージ エンジンを使用している場合でも、users.id が int の場合、単一のトランザクションを作成して複数の行を更新するようにだますことができます。

$update = $mysqli->prepare('UPDATE users SET emailed=1 WHERE id IN (' . implode(',', $u) . ')');
$update->execute();
$update->close();

foreach($users as $user)代わりにステートメントを閉じた後

于 2012-09-17T23:21:08.793 に答える
-5

より効率的なスクリプトを作成するか、より優れたハードウェアを入手してください。

編集:

大量の電子メール送信に関しては、スクリプトにタイムアウトを追加して、すべての電子メールをできるだけ早く処理しないようにすることができます。これにより、CPU の負荷が軽減されますが、スクリプトの時間が長くなります。

例えば:

for(all emails)
{
   //send email
   sleep(5);
}
于 2012-09-17T16:40:11.697 に答える