3

我正在开发带有实时竞价系统的现场拍卖网站。当用户对项目出价时,我正在使用LONG POLLING 。我选择了长轮询,因为WebSockets还没有得到很好的支持,而且NODEJS对我来说现在实现起来很复杂。所以我坚持使用这个简单的 ajax 长轮询,它适用于大约五个投标。

所以问题是:在 1 秒的时间间隔内,投标对 5-6 个项目的投标非常有效(我从 server-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>

投票.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

考虑切换到 WebSockets。它旨在解决长轮询问题。

于 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 回答