你好.
問題描述:
在一個推送非常頻繁的場景下,可能同一時間有N(N>5)條消息推送到web頁面
現(xiàn)在發(fā)現(xiàn)會有偶爾漏掉消息的情況, 請問這個問題大概是哪個環(huán)節(jié)的問題.以及如何避免這個情況?
可能的情況
1、業(yè)務(wù)問題,實際有的消息沒有發(fā)送。(需要服務(wù)端把發(fā)送的消息在send前記錄在磁盤上作為日志)
2、消息推送到網(wǎng)頁了,但是因為網(wǎng)頁js業(yè)務(wù)代碼有bug導(dǎo)致沒展示。(chrome 瀏覽器按f12 在network ->ws->Frames 里能看到服務(wù)端傳來的數(shù)據(jù),能確認(rèn)服務(wù)端是否發(fā)送過來或者是否有缺失)
3、如果服務(wù)端推送非常頻繁,并且客戶端接收速度小于服務(wù)端發(fā)送速度,會導(dǎo)致消息擠壓在內(nèi)存緩沖區(qū)中(每個連接一個緩沖區(qū)),如果這種情況一直持續(xù),會最終導(dǎo)致緩沖區(qū)滿,導(dǎo)數(shù)據(jù)丟失。參考http://doc.workerman.net/315150 。如果有這種情況,運行php start.php status 里的send_fail字段會有非0的值,而且這個值一般會比較大。如果業(yè)務(wù)不能忍受丟失數(shù)據(jù),可以監(jiān)聽onBufferFull,然后將數(shù)據(jù)寫入磁盤,當(dāng)onBufferDrain時從磁盤讀出數(shù)據(jù),繼續(xù)發(fā)送。
應(yīng)該是第三種情況,剛研讀了一下幫助文檔關(guān)于onBufferFull和onBufferDrain的,但還是不知道如何下手寫這個數(shù)據(jù),不知道能否給一個簡單的示例. onBufferFull的參數(shù)里并沒有data數(shù)據(jù),那我從何處保存這個數(shù)據(jù)?直接跟onMessage一樣保存post過來的數(shù)據(jù)嗎? 另外,如果我把maxSendBufferSize的值設(shè)置的足夠大能解決問題嗎?
onBufferFull 是在上一次 send 之后發(fā)現(xiàn)緩沖區(qū)滿了觸發(fā)的(但上一次 send 的數(shù)據(jù)并沒有丟失),所以這只是一個通知,用于提醒你暫時不要再 send 了。
maxSendBufferSize 太大,如果客戶端接收速度慢,服務(wù)端一直發(fā)送maxSendBufferSize還是會滿。maxSendBufferSize太大如果buffer滿了,也會導(dǎo)致程序占用內(nèi)存變大。
如果你的場景只是瞬時流量波動比較大,平均下來相對于傳輸帶寬還是沒問題的,那么最簡單的辦法是擴大發(fā)送緩沖區(qū)(只要峰值別大到內(nèi)存爆掉),就可以了。
但如果是平均流量比傳輸帶寬還大,那么持續(xù)下來,多大的發(fā)送緩沖區(qū)也不夠用,【寫入硬盤】的辦法也一樣不夠用,那就只能從業(yè)務(wù)邏輯層面重新規(guī)劃了。
是的,我的場景就是會瞬間可能比較多條推送,但總體不算很大.只是瞬時的時候會丟失一些數(shù)據(jù). 我現(xiàn)在處理一下web前端的dom操作流程優(yōu)化,再擴大一下maxSendBufferSize的值試試.