公司的一款即時通訊web產品,之前設計的架構是聊天訊息定期從IM伺服器獲取,這會導致如果使用者重新整理頁面,會丟失最近的聊天對話訊息。由於之前定時間隔在分鐘級別,所以問題不是很明顯。最近由於種種原因,訊息同步間隔變長到小時級別,從而將訊息丟失的問題凸顯出來,工單不斷。
設計思路
採用localstorage實現web端本地訊息快取是這次設計的主體思路。因為產品對低版本瀏覽器預設不支援,因此也就不需要考慮瀏覽器的相容性問題。關於localstorage的介紹請參見(developer.mozilla.org/zh-CN/docs/…);
- 進入頁面,檢查一下本地快取的粉絲訊息是否過期,如果過期,則清除。以粉絲為單位;
- 點選某個粉絲,從伺服器獲取20條歷史訊息。獲取該粉絲本地快取訊息,兩者以最新時間對比,如果伺服器是最新的,就清除該粉絲本地快取,並且同步本地快取。如果本地最新,則採用本地快取。其考慮的主要目的是考慮到當前離下一次伺服器同步很近,且使用者又在其他電腦上與該粉絲聊過的場景,保證最快更新到本地快取;
- 主動傳送和接收到的聊天訊息,push到該粉絲對應的本地佇列。(檢查訊息條數封裝在內部實現);
- 客服關閉該粉絲,或重新整理了本頁面。當再次切換到該粉絲時,重複步驟 1 ;
評估:
locastorage的最大配額各瀏覽器基本是5MB。以下的計算都是估算,大致認為1KB=1000byte,1MB=1000KB。實際是以1024 換算。這裡只估算。
如果需要快取50個粉絲,那麼每個粉絲分配的空間:5MB/50=0.1MB=100KB;
假設一個訊息100位元組(1個英文字元佔1個位元組,漢字屬於雙位元組,佔兩個位元組)。那麼每個粉絲可以快取訊息數:100KB/100byte=100 * 1000/100=1000 條
定義配置引數:
- fansLimit:50;快取的粉絲個數
- msgLimit:100;快取的粉絲訊息條數;
- expired:1000 60 60 * 2;快取有效時間,單位:ms;
快取格式:
- 在localStorage上定義個快取變數:msgCache。裡面儲存的每個欄位對應一個粉絲的快取;
- 以粉絲的id為key,{{fansid}},值為物件。例如:{time:122222222,msgs:[{msg}]}
- fansid:粉絲的id;
- time:最新的活躍時間。每次新增快取的時候同步更新.存毫秒值格式;
- msgs:快取粉絲的具體業務資料陣列,每一項代表一條訊息,訊息的格式參見業務訊息object即可。
檢查內容:
- 粉絲訊息過期檢查(A),檢查粉絲的最新活動時間是否超過設定的過期時長,超過則remove該粉絲快取;
- 粉絲訊息條數檢查(B),檢查改粉絲條數如果超過限制,刪除最早的訊息,直接用佇列,先進先出;
- 刪除粉絲快取(C);直接刪除粉絲快取
快取檢測時機:
- 頁面載入時遍歷粉絲快取,執行A;
- 讀取localstorage的時候,執行A;
- 設定粉絲訊息快取的時候,執行B;(這裡可以不用執行A)
- 設定快取出現異常(quotaExceedError,表示超過localstorage最大限制),執行C;
總結
- 關於快取超出最大配額的處理比較粗糙,可以考慮設計一種動態擴容的方案;
- 如果使用者在聊天過程中更換了電腦,瀏覽器產品,還是會有訊息丟失的情況;
- 最根本的解決方案,還是由服務端實時儲存聊天訊息記錄。