2012-12-07 39 views
6

我正在構建一個用於監控私人聊天室的後端模塊(用PHP編寫),該聊天室對於[完全] 300秒(5分鐘)沒有任何活動。如果是,腳本將更新數據庫(將最大用戶數設置爲某個數字,以及其他內容)。我正在通過now()和上次發送的消息的時間差來監視空閒時間的跨度。PHP連續檢查數據庫更改的最佳做法是什麼?


我做了什麼:設置一個cron作業,每分鐘或60秒將運行(通過php-cli)我的監視腳本。裏面的監控腳本:

$expire_time = time() + 60; 

//this loop will run for 60 seconds 
while(time() < $expire_time) 
{ 
    $idle_time = get_all_chatrooms_idle_time(); 
    foreach($idle_time as $s_time) 
    { 
    if($s_time >= 300) 
    { 
     update_changes(); 
    } 
    } 
    usleep(500000); 
} 

的空閒時間立即設置最​​大用戶後經過300秒的條件,不能討價還價。所以我不能真正遵循這樣的建議:「避免做任何事情,直到事實上要求它」,即使它很有意義。

原因?活動和不活動聊天室的數據需要實時,因爲它也會顯示在儀表板上。聊天室版主的薪水取決於它。


爲什麼不檢查他們每個儀表板的負載?我很抱歉,但仍然不可能。

檢查需要服務器端,儀表板使用ajax進行更新,每秒進行一次輪詢。

當我裝上監控代碼的頁面被請求我的Ajax調用我覺得它比我目前的執行佔用更多的資源(糾正我,如果我錯了)

讓我給你上號了一些粗略的估計用戶的所以你可以想象負載/流量我們得到:

  • 數聊友,包括主持人:〜800
  • 號聊天室:〜250
  • (x)的聊天室版主的數量:〜 50
  • (X)我的老闆和他的員工:

(X) - 可以查看儀表板


有沒有更好的辦法?我做對了嗎?

+0

好像你做錯了。有沒有聽說過CRON工作?我認爲上帝的做法是每隔1分鐘(或更少)設置cron作業?這將使用select運行簡單的MySQL腳本。 – Stranger

+0

可能的重複http://stackoverflow.com/questions/4834829/php-long-polling-without-excessive-database-access –

+0

@Stranger我做過了嗎? – yowmamasita

回答

1

此循環過度。它可能每分鐘運行數千次,即使是在中等的服務器上,即使對於實時應用程序,它也會產生高CPU使用率。添加一個計數器,並查看迭代次數。我認爲這會產生比每次AJAX請求處理更多的負載。

首先,確定您需要的信息的粒度。假設你選擇了3秒的粒度(例如每3秒掃描一次數據庫) - 這個數字對你來說可能太高了,但它說明你不會損失太多。有了AJAX,你每秒鐘都可以看到一些計數器,它們應該不斷爬取一次或兩次。 (你是否真的會看到這樣的事情取決於你的櫃檯的性質。)

如果您的計數器基於數秒範圍內的數據(例如,顯示經過的秒數的總和或基於$ /秒的數量),則第二個AJAX拉動將不會提供連續的計數器。 (由於網絡原因,它有時會錯過一秒或更新到那一秒)。

無論選擇的粒度如何,您的最終統計數據都是正確的,因爲它們基於絕對時間戳 - 無論它們評估得有多晚。

如果使用第二方面的AJAX輪詢來實現平滑計數器,則可以做得比這更好:計數應該在客戶端運行(例如,使用它們的第二個遞增值發送值:revenue: <span data-inc="25">14432</span>並用JS計數) 。唯一實現AJAX來監視停止/重置計數器的條件。那麼你只需要確定通知可能會延遲多久(例如10秒),那麼計數器將超過最大值。 10s跌回預期值。在這種情況下,您不應該更頻繁地運行數據庫清理(例如,間隔的一半)。這允許例如在您的週期中進行3秒鐘的睡眠,從而大幅降低負載。

如果您可以輕鬆選擇將每個聊天室的過期時間戳添加到數據庫(記錄中或固定的),並且索引可以加快閱讀速度(另外還允許按照每個房間的過期規則)。

+1

如果您想將它用於例如可以輕鬆訪問已經編寫的BL代碼。它僅作爲服務(實時跟蹤服務)持續運行。在一個可以殺死運行時限制的系統上,你至少可以這樣設置:創建一個邏輯sleep()s,直到下一個可能的事件[例如下一屆到期或最小可能到期期限]。如果你必須忍受運行時限制,你仍然可以使用你現在使用的方案(每分鐘完成一個腳本,一分鐘後退出),只需添加一些sleep()! –

+0

我真的很抱歉,但代碼有usleep(500000),我忘了添加。 500ms睡眠時間基於我們服務器對大多數客戶的平均延遲。所以...循環:每秒最多2個呼叫,ajax民意調查:如果有60個觀衆,每秒60個呼叫。 – yowmamasita

+1

好的,你正處在正確的軌道上。關於客戶端計數以允許降低檢查延遲的建議仍然適用。獨立地,休眠到下一個可能事件的可能性也適用:如果您的選擇表明下一個到期時間在X秒之後(取大值,如果當前沒有開放式聊天室)以及系統中的最短到期時間(即使計算可能的房間被創建)是Y秒,那麼你可以睡覺最小(X,Y),而不需要重新檢查;然後檢查,可能的過程,並確定一個新的X. –

1

我根據評論,推薦使用諸如node.js這樣的技術,它是一個偶數驅動的I/O異步平臺,用於構建應用程序。如果聊天室是一個外部應用程序,您可以輕鬆打開一個套接字並聽取聊天室,記錄日誌,檢查用戶的活動並監聽特定事件。

+0

(我做對了嗎?)在聊天消息輸入,函數update_max_users(),settimeout update_max_users()到300秒 – yowmamasita

1
#!/usr/bin/php 
<?php 

if(file_exists('/tmp/chatrooms_cron.lock')) { 
    die('There is already a script running.'); 
} 

file_put_contents('/tmp/chatrooms_cron.lock', 1); // Storing pid would be better 

// Run loop forever 
while(true) 
{ 
    $idle_time = get_all_chatrooms_idle_time(); 

    foreach($idle_time as $s_time) 
    { 
    if($s_time >= 300) 
    { 
     update_changes(); 
    } 
    } 

    sleep(60); 
} 

提示用於node.js的(與socket.io):

我一直在使用Node.js的,在其偉大的工作!將實時並與瀏覽器一起工作到ie5/ie6。這可以在node.js內部完成。

setInterval(function() { 
    // Fetch and update peers 
}, 300000); 
相關問題