教你六种方式实现聊天室
如果技術棧不一致的同學請盡量看懂架構和概念,自己用自己的技術棧去架構自己的聊天室!
此項目為前后端分離項目,基于vue+springboot構建
歡迎star
前端:以 vue 為核心的 vue全家桶(vue+vuex-狀態管理+vue-router-路由管理+axios-HTTP庫),UI框架使用了iview+VueSax,打包和初始化項目工具使用 webpack 來代替vue-cli.圖片上傳使用了他人的 圖床,發送框使用了 quill 富文本編輯器。
后端:使用了springboot 框架,數據持久層框架使用了 mybatis,數據庫使用mysql.
中間件:緩存中間件-redis,消息隊列-rabbitmq。
加密使用 AES 加密
通訊協議使用 WebSocket和HTTP協議
項目演示:
1.登錄注冊部分
由于登錄注冊太過于簡單,所以這里直接給出賬號密碼名單使用
當此賬號已經登錄時,isOnline 開關會顯示打開狀態,點擊登錄會出現提示
切換另一個賬號即可,若無可用賬號,請等待 orz
2.聊天
注:這個項目里只有群聊,沒有設置單人聊天,因單人聊天無非是群聊的一個特例,這里不予實現。
主界面
項目里給出了6個聊天室,分別對應不同實現方式。
–聊天室一:
僅使用WebSocket實現,僅能在線聊天,離線用戶收不到消息且無法讀取未讀消息
如圖,前端通過http協議向后端發送數據,后端接收到數據后通過WebSocket協議向在線的人員發送數據。
–聊天室二:
使用`WebSocket+mysql`,提供了在線聊天,不在線用戶上線后可拉取未讀消息。
如圖,后端接收到聊天數據并給在線人員發送消息后再把數據按照一定的邏輯存在數據庫里,當用戶上線后,拉取未讀消息即可,此時未讀消息能且僅能拉取一次,拉取完畢后,消息就成為已讀消息,并不能重讀拉取。
–聊天室三:
緩存寫擴散:使用WebSocket+redis+mysql。
如圖,每個用戶維護一個 inBox,每條信息發給服務器時,給在線人員發生信息,并判斷該條消息所屬群組,并找到該群組下所有不在線人員,并把該消息寫入不在線人員下的inBox下,當用戶上線拉取消息時,只需從自己的 inBox 下拉取消息即可,該inBox是用redis的list實現的,是有序的(插入順序),所以不存在消息時間混亂問題,當用戶讀取消息后,立即刪除該inBox,保證了未讀消息的唯一性.其中mysql用于消息的備份。
–聊天室四:
緩存讀擴散:使用WebSocket+redis+mysql。
如圖,每個用戶需要維護一個outBox和一個已讀消息索引,用戶每發送一條信息,都存在自己的outBox里面,并存入order順序表,當離線用戶上線拉取未讀消息時,首先讀取自己已讀消息索引和order順序表,根據順序表大小和已讀消息索引之差找到自己所有未讀消息,然后根據順序表里的信息去找每一條信息發送者的outBox,并拉取每一條未讀消息,拉取完畢后更新自己的已讀消息索引即可。
–聊天室五:
緩存讀擴散改良版:使用WebSocket+redis+mysql。
在上一個聊天室中,由于每個用戶有一個outBox,信息存儲將是無序的,所以需要額外耗費空間來存儲順序,所以在改良版中,根據是群組的信息發送,所以只需維護一個群組的outBox,不再有個人的outBox,所以用戶拉取歷史消息時,只需比對自己消息索引和群outBox索引即可
– 聊天室六
消息隊列:使用 WebSocket+Rabbitmq+mysql
這里使用rabbitmq作為消息中間件,每個群組是一個fanout 類型交換器,這個交換器的特點在于,每接收一條消息,交換器都會給綁定的隊列發送這條消息,所以每個群組綁定一個fanout類型交換器,每個交換器下都綁定這每個用戶的隊列,用戶每發送一條消息,每個隊列都會收到這條消息,在線的用戶把消息讀取出去,不在線的用戶上線拉取消息,這樣的方式減少了手動判斷用戶和減少關注消息的順序問題,統一交給消息隊列處理。
三、其他
- UI優化
登錄過期提醒
新消息提醒
發送圖片 - 消息存儲
前端所有消息均存在 localstorge中,當前后登錄賬戶不一致時,前一個賬戶消息將會被清空,如果前后登錄賬戶一致,消息不會清空
用戶登錄有效期在 30 分鐘內,超過30分鐘要重新登錄
總結
以上是生活随笔為你收集整理的教你六种方式实现聊天室的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 经典炖鸡汤做法
- 下一篇: js-最常用的js表单校验1