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