2

CURL経由でwww.server.comにHTTPリクエストを送信する機能があります

私の仕事は、www.server.comが2秒ごとに1つ以下のリクエストを受け取るようにすることです。

考えられる解決策:

checktime()現在の通話時間をデータベースに保存し、次の通話ごとにデータベースを確認して、システムを2秒間一時停止する関数を作成します。

$oldTime = $this->getTimeFromDatabase();
if ($oldTime < (time() - 2) ) { // if its been 2 seconds
  $this->setNewTimeInDatabase(); 
  return true;
} else {
  sleep(2);
  return false;
}

問題/質問:

たとえば、www.server.comへの最後のリクエストは1361951000でした。その後、他の10人のユーザーが1361951001(1秒後)にリクエストを実行しようとします。checktime()関数が呼び出されます。

たった1秒なので、関数はfalseを返します。10人のユーザー全員が2秒待ちます。1361951003に10個のリクエストが同時に送信されることを意味しますか?また、$ this-> setNewTimeInDatabase()の呼び出しが失敗したために、データベースで最後の要求の時刻が変更されない可能性はありますchecktime()か?

ありがとうございました!

アップデート:

ループを使用すると問題が解決する可能性があると言われました。

for($i=0;$i<300;$i++)
{
   $oldTime = $this->getTimeFromDatabase();
   if ($oldTime < (time() - 2) ) { // if its been 2 seconds
   $this->setNewTimeInDatabase(); 
   return true;
   } else {
    sleep(2);
    return false;
   }
}

しかし、私は実際にはその中に論理を見ていません。

4

2 に答える 2

2

セマフォの実装が必要だと思います。1つのスレッドだけがデータベースに書き込み、要求を行うことを保証できる限り、データベースは機能します。

たとえば、データベースへの更新要求を使用してから、更新された行を確認できます(更新が実際に行われたかどうかを確認するため)。更新が成功した場合は、ミューテックスロックを取得したと見なしてから、要求を行うことができます(それを行うのに適切な時期であると想定しています)。このようなもの:

$oldTime = $this->getTimeFromDatabase();
if ($oldTime < (time() - 2) && $this->getLock()) { // if its been 2 seconds
  $this->setNewTimeInDatabase(); 
  $this->releaseLock();
  return true;
} else {
  sleep(2);
  return false;
}  

function getLock()
{
    return $mysqli->query('UPDATE locktable set locked = 1 WHERE locked = 0');
}

function releaseLock()
{
     $mysqli->query('UPDATE locktable set locked = 0');
}

mysql関数についてはよくわかりませんが、一般的な考え方を理解しても問題ないと思います。

于 2013-02-27T20:34:36.070 に答える
1

データベースの使用に注意してください。たとえば、MySQLは常にそのセッションと100%同期しているわけではないため、ロックの目的でMySQLに依存することは安全ではありません。

メソッドflockを介してファイルロックを使用すると、アクセス時間を節約できます。その後、ファイルを確実にロックできるため、2つ以上のプロセスが同時にファイルにアクセスすることはありません。

それはおそらく次のようになります:

$filepath = "lockfile_for_source";
touch($filepath);
$fp = fopen("lockfile_for_resource", "r") or die("Could not open file.");

while(true){
  while(!flock($fp, LOCK_EX)){
    sleep(0.25); //wait to get file-lock.
  }

  $time = file_get_contents($filepath);
  $diff = time() - $time;
  if ($diff >= 2){
    break;
  }else{
    flock($fp, LOCK_UN);
  }
}

//Following code would never be executed simultaneously by two scripts.
//You should access and use your resource here.

fwrite($fp, time());
fflush($fp);
flock($fp, LOCK_UN); //remove lock on file.
fclose($fp);

私はコードをテストしていないことに注意してください。

于 2013-02-27T20:26:27.700 に答える