2012-06-23 62 views
1

我有一個Web應用程序,我試圖通過減少運行的數據庫查詢的數量來提高效率。我傾向於實施某種類型的Comet風格解決方案,但是我在這個部門缺乏經驗讓我懷疑是否存在更簡單的解決方案。彗星(服務器推送)我在找的答案?

爲簡便起見,我們只想說,我有一個包含網絡,其當前狀態的系統列表(無論是向上或向下)的數據庫。用戶可以登錄Web應用程序並選擇她感興趣監視的系統。之後,她可以訪問顯示當前系統數量的監控頁面。

截至目前,使用Ajax刷新計數...客戶端每隔一分鐘向服務器發送一個請求,服務器依次對數據庫運行查詢以獲取當前計數並將結果返回給客戶端。我知道這是低效的;對於每個登錄的客戶端,每分鐘都會對數據庫運行另一個查詢。 O(n)=壞!

我知道我可以使用某種類型的緩存,如分佈式緩存,但它仍然意味着它的每分鐘每個用戶的請求。更好,但我仍然覺得它不是最好的解決方案。

我想象更多的東西是這樣的:

  • 每一分鐘的服務器運行一個查詢拉計數所有目前下跌的系統。
  • 服務器然後將這些數據推送到感興趣的客戶端。

這樣無論登錄多少用戶並觀看監控頁面,服務器每分鐘只運行一個查詢。 O(1)=好!問題是,即使在我所做的所有研究之後,我都無法完全弄清楚如何實現這一點。說實話,我並不完全理解我在尋找什麼,所以這使得研究解決方案變得非常困難。所以我希望更多開明的開發者能夠帶領我走向正確的方向。

回答

0

解決這個問題,可以很容易地被稱爲Pusher的應用程序,這是一個託管的發佈/訂閱API解決。在一個堅果殼中,Pusher提供了兩個庫,一個用於客戶端(訂戶),一個用於服務器(發佈者)。

發佈者可以是您的服​​務器(there are quite a few languages available)設置爲你想要的任何間隔運行一個腳本。每次運行時,它都會連接到一個通道並將其生成的任何數據發佈給它。客戶端是通過您的Web應用程序中的一些JavaScript創建的,每當用戶導航到您的頁面時,客戶端都會訂閱您的服務器腳本發佈到的相同頻道,並在數據可用後立即接收數據,然後可以操作但是你認爲合適。

服務器:

#!/usr/bin/php 
<?php 
require('Pusher.php'); 

$dbh = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass); 
foreach($dbh->query('SELECT hostname FROM systems WHERE status = 0') as $row) { 
    $systems[] = $row['hostname']; 
} 
$pusher = new Pusher($pusher_key, $pusher_secret, $pusher_app_id); 
$pusher->trigger(
    'my-channel', 
    'my-event', 
    array('message' => implode('<br />', $systems)) 
); 

客戶端:

<!DOCTYPE html> 
<html> 
    <head> 
    <title>Pusher Test</title> 
    <script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script> 
    <script src="http://js.pusher.com/1.12/pusher.min.js" type="text/javascript"></script> 
    <script type="text/javascript"> 
     var pusher = new Pusher(key); 
     var channel = pusher.subscribe('my-channel'); 
     channel.bind('my-event', function(data) { 
     $('#systems').html(data.message); 
     }); 
    </script> 
    </head> 
    <body> 
    <div id="systems"></div> 
    </body 
</html> 

所以,在這種情況下,無論多客戶端如何訪問該頁面只有一個數據庫查詢運行情況,在每個時間間隔內,所有訂閱的客戶端都將使用新數據進行更新。

還有一個用Ruby編寫的Pusher協議的開源服務器實現,名爲Slanger

0

你可以用彗星做。但是,您也可以每隔一分鐘左右有一個JavaScript計時器輪詢服務器。這取決於你想要反饋的速度。它不需要一直保持TCP連接打開。

此外,您瞭解服務器狀態的方法是獨立於客戶端獲得該信息的方式。每當客戶端請求時,您都不想更新服務器的狀態。相反,你應該在應用服務器上有一個定時器來輪詢服務器狀態,然後存儲它。客戶端請求將從這個存儲狀態提供,而不是實際的實時狀態。

+0

我相信你剛纔提到的長輪詢,不是嗎?在這兩種情況下,客戶端仍然在發送請求,導致服務器採取行動,這正是我想要避免的。 此外,每次客戶端請求時系統的狀態都不會更新。該數據已經保存在數據庫中,並獨立於此過程進行更新。當客戶端發送請求時,服務器正在對數據庫運行查詢以爲每個系統提取最近存儲的狀態。 – jonyamo

+0

好的,我的答案的第二部分已經被清除了。回覆。第一部分:彗星解決方案是一種長期投票。我的建議不是長時間輪詢,而是在特定的時間間隔內做短暫的請求。這意味着客戶端不會立即通知服務器狀態的變化,而只是每隔一段時間。 – Wolfgang