3

リアルタイム入札システムを備えたライブ オークションサイトを開発しています。ユーザーがアイテムに入札するとき、私はLONG POLLINGを使用しています。WebSocketはまだあまりサポートされておらず、NODEJSは複雑すぎて今すぐ実装できないため、ロング ポーリングを選択しました。だから私はこのシンプルな ajax ロング ポーリングにこだわっています。これは約 5 つの入札でうまく機能します。

したがって、問題は次のとおりです。入札は1秒間隔で5〜6個のアイテムの入札に対してうまく機能します(サーバーajaxから即座に応答します)が、入札ボタンの7番目(クリック)で、この応答の長いポーリングは約16〜22秒間ハングしますそしてリクエストを完了します。最後に、すべてがデータベースで更新されて完了しますが、5 ~ 6 回入札するたびに、応答 / ajax 呼び出しが約 16 ~ 22 秒間ハングします。

ユーザーの入札回数に関係なく、遅延なくすべてがスムーズに進むように、この時間をどのように短縮できますか...

localhost/wamp で Apache/PHP/MySql を使用しています

私のコード: index.php

<script type="text/javascript" charset="utf-8">             
var old_timestamp = <?php echo $old_timestamp;?>; //here i'm echoing last timestamp of         auction

function waitForMsg(){
jq.ajax({
type: "POST",
url: "http://localhost/bid/comet/poll.php",
data: {"old_timestamp" : old_timestamp},
async: true,
cache: false,

success: function(data){
var json = eval('(' + data + ')');
if(json['msg'] != "") {
jq('#comet_display').html(json['msg']); //here I show ID of which auction item was bidded
}
old_timestamp = json['old_timestamp']; 
setTimeout('waitForMsg()',100);
},
error: function(XMLHttpRequest, textStatus, errorThrown){

setTimeout('waitForMsg()',1000);
}
});
}

jq(window).load(function(){ 
waitForMsg();
jq("#a_loader").show();
    var url = "http://localhost/bid/auctions-ajax"; // the script where you handle the form input.  
    jq.ajax({
           type: "POST",
           url: url,
           data: {au978 : true}, 
           async:false, //to sem dodal za časovni zamik
           success: function(data)
           {
             jq("#a_loader").hide();  
             jq("#show-category").html(data); // show response from the php script.              
           },
            error: function(result) {
                jq("#show-category").html("Sorry, something went wrong. Please try again later.");
            }
    });

});

function bid(id){

var url = "http://localhost/bid/comet/update-auction.php"; // the script where you handle the form input.
var user_id=<?php echo $user_id;?>; //user id from session
jq.ajax({
    type: "POST",
    url: url,
    data: {"auct_id" : id, "user_id" : user_id}, // serializes the form's elements.
    success: function(data)
    {
        //it updates in user table its remaining number of bids 
    },
    error: function(XMLHttpRequest, textStatus, errorThrown){
        alert("Something went wrong. Click OK to refresh.");

    }
});
}

</script>

poll.php

<?php

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/include/DEFINES.php');
require_once(CLASS_AUCTION);
require_once(CLASS_DB);

$a=new Auction();

$old_timestamp = $_POST['old_timestamp']; 
$bidded_id=0;
$db=DB::getInstance();  
$sql="SELECT timestamp, id FROM auction ORDER BY timestamp DESC LIMIT 1";   //desno doda tabelo kategorija  
$stmt=$db->db->prepare($sql) or die("Prepare Error");   
$stmt->execute();   
$result2=$stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($result2 as $rez){
    $current_timestamp=$rez['timestamp'];   
    $bidded_id=$rez['id'];
}
$stmt->closeCursor();


    while($current_timestamp <= $old_timestamp){
    usleep(1000);
    clearstatcache();
    $db=DB::getInstance();  
    $sql="SELECT timestamp, id FROM auction ORDER BY timestamp DESC LIMIT 1";       
    $stmt=$db->db->prepare($sql) or die("Prepare Error");   
    $stmt->execute();   
    $result=$stmt->fetchAll(PDO::FETCH_ASSOC);
    foreach ($result as $rez){
        $current_timestamp=$rez['timestamp'];   
        $bidded_id=$rez['id'];
    }
    $stmt->closeCursor();

}
$response = array();
$response['msg'] = 'BID na avkciji: '.$bidded_id;
$response['old_timestamp'] = $current_timestamp;
echo json_encode($response);
 }else{
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/errors/404.html');
 }
?>

および update-auction.php

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/include/DEFINES.php');
require_once(CLASS_AUCTION);
require_once(CLASS_USER);
require_once(CLASS_DB);
$u=new User(); 
$a=new Auction();
$auction_id=$_POST['auct_id'];
$user_id=$_POST['user_id'];
$date = new DateTime();
$timestamp=$date->getTimestamp();
$a->updateAuction($auction_id,$user_id,$timestamp/*,$bid_price,$bids_spent,$total_paid*/);
$u->updateUserBids($user_id);

}else{
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/errors/404.html');
}
?>

私の問題をご覧いただきありがとうございます!

4

2 に答える 2

0

WebSocket への切り替えを検討してください。長いポーリングの問題を修正するために設計されました。

于 2013-03-23T18:05:58.063 に答える
0

わかりました、この 17 ~ 22 秒の LAG-HANGING 問題を解決する解決策を見つけました。クリック回数に関係なく、ほぼ瞬時に表示されます。しかし、これがロングポーリングの最良の解決策であるかどうかはまだわかりません。

誰かが同じ問題を抱えているなら、私はそれを投稿しています。

poll.php の LONG POLLING 関数を次のように変更しました。

<?php

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/include/DEFINES.php');
require_once(CLASS_AUCTION);
require_once(CLASS_DB);

$a=new Auction();
$db=DB::getInstance();  
$sql="SELECT timestamp, id, last_username FROM auction ORDER BY timestamp DESC LIMIT 1";        
$response = array();
while(1)
{
    $stmt=$db->db->prepare($sql) or die("Prepare Error");   
    $stmt->execute();   
    $result=$stmt->fetch(PDO::FETCH_ASSOC);
    if (!empty($result)){
        $current_timestamp=$result['timestamp'];        
        $response['msg'] = 'New BID';
        $response['old_timestamp'] = $current_timestamp;
        echo json_encode($response);
        break;
    }   
    sleep(3000);
    clearstatcache();
}
}else{
require_once($_SERVER['DOCUMENT_ROOT'] . 'bid/errors/404.html');
}
?>

そして今、私は次のようにindex.phpでポーリングしています:

<?php
$db=DB::getInstance();  
$sql="SELECT timestamp FROM auction ORDER BY timestamp DESC LIMIT 1";    
$stmt=$db->db->prepare($sql) or die("Prepare Error");   
$stmt->execute();   
$result2=$stmt->fetch(PDO::FETCH_ASSOC);
$old_id=0;
$last_timestamp=$result2['timestamp'];
?>
<script type="text/javascript" charset="utf-8">             
var last_timestamp = <?php echo $last_timestamp;?>;
var old_timestamp=0;

function waitForMsg(){
jq.ajax({
type: "POST",
url: "http://localhost/bid/comet/poll.php",
async: true,
cache: false,

success: function(data){
var json = eval('(' + data + ')');
if(old_timestamp==0 || last_timestamp==old_timestamp){

}else{
    if(json['msg'] != "") {
    jq('#comet_display').html(json['msg']);
}
}
old_timestamp = json['old_timestamp']; 

setTimeout('waitForMsg()',500);
},
error: function(XMLHttpRequest, textStatus, errorThrown){

setTimeout('waitForMsg()',1000);
}
});
}

jq(window).load(function(){ 
waitForMsg();

});
function bid(id){   
var url = "http://localhost/bid/comet/update-auction.php"; //here I update auction and user's bids
var user_id=<?php echo json_encode($user_id);?>;
var user_name=<?php echo json_encode($user_name); ?>;
jq.ajax({
    type: "POST",
    async: true,
    cache: false,
    url: url,
    data: {"auct_id" : id, "user_id" : user_id, "username" : user_name}, // serializes the form's elements.
    success: function(data)
    {

        setTimeout('waitForMsg()',100);
        var cnt = parseInt(jq(".db_bids").text());
        if (!isNaN(cnt))
        {
            cnt--;
            jq(".db_bids").text(String(cnt));
        }    
    },
    error: function(XMLHttpRequest, textStatus, errorThrown){
        alert("Something went wrong. Click OK to refresh.");

    }
});
}
</script>

私はまだ localhost でこれを開発しています。100 人以上のユーザーがいる実際のサーバーでこれがどのように動作するかを確認します。 データベースからの LONG POLLING を使用した、より優れた高速なソリューションがあれば、お知らせください:)

于 2013-03-24T17:23:51.180 に答える