Question

I'm developing live auction site, with real-time bidding system. I'm using LONG POLLING when user bids on item. I've chose long polling because WebSockets are not yet very supported and NODEJS is to complicated for me to implement right now. So I'm stuck with this simle ajax long polling, which works great for about five bids.

So the problem is: Bidding works great for 5-6 item bids in 1 second intervals (I get instant response from server-ajax), but the 7th (click) on bid button this response-long polling hangs for about 16-22 seconds and then completes the request. At the end everything is updated in database and completed but after every 5-6 bids response/ajax call hangss for about 16-22 seconds.

How could I reduce this time, that everything should go smoothly no matter how many times user bids, without lag...

I'm using Apache/PHP/MySql on localhost/wamp

My code: 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');
 }
?>

and the 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');
}
?>

Thank you for viewing my problem!

Était-ce utile?

La solution 2

Ok, I have find a solution which fixes this 17-22 seconds LAG-HANGING problem. Now it's almost instant, regardless how many times you click. But I'm still not sure, if this is the best solution of long polling.

I'm posting it, if someone would have the same problem.

I've changed LONG POLLING function in my poll.php to this:

<?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');
}
?>

and now i'm polling in my index.php like this:

<?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>

I'm still developing this on localhost & will see how this behaves on real server with 100+ users. If anyone have better and faster solution with LONG POLLING from databases, please let me know :)

Autres conseils

Consider switching to WebSockets. It was designed to fix the long polling issue.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top