介紹
即時(shí)通訊應(yīng)用服務(wù)孽惰,整套包含服務(wù)端贩绕、管理端和客戶端
預(yù)計(jì)3篇分享:這次是第一篇,項(xiàng)目的整體介紹和實(shí)體關(guān)系的梳理
現(xiàn)已部署上線猴贰,客戶端和管理端,歡迎體驗(yàn)
可以注冊(cè)客戶端賬號(hào)河狐,也可以使用初始默認(rèn)賬號(hào)米绕,現(xiàn)有初始賬號(hào)說(shuō)明:
賬號(hào) | 密碼 | 說(shuō)明 |
---|---|---|
admin | 123456 | 管理端賬號(hào) |
user | 123456 | 客戶端普通用戶賬號(hào) |
muteuser | 123456 | 客戶端被禁言用戶賬號(hào) |
disabled | 123456 | 客戶端被封禁用戶賬號(hào) |
member1 | 123456 | 客戶端普通用戶賬號(hào) |
member2 | 123456 | 客戶端普通用戶賬號(hào) |
... | 123456 | 客戶端普通用戶賬號(hào) |
member30 | 123456 | 客戶端普通用戶賬號(hào) |
<img width="300" src="https://i.loli.net/2020/07/15/fO2naUmPluYRsBd.png">
功能簡(jiǎn)介
- 注冊(cè),登錄馋艺,個(gè)人栅干、群組聊天,個(gè)人信息編輯等基礎(chǔ)功能
- 申請(qǐng)?zhí)砑雍糜押蜕暾?qǐng)入群
- 表情捐祠,圖片碱鳞,視頻,定位信息支持
- 聊天會(huì)話列表記錄
- 消息記錄(微信的消息記錄真實(shí)一言難盡)
- 支持多點(diǎn)同時(shí)登錄
- 百度 UNIT 機(jī)器人自動(dòng)回復(fù)(todo)
- 管理端踱蛀,進(jìn)行角色和權(quán)限的管理窿给,群狀態(tài)管理(我也當(dāng)一回馬化騰)
需求簡(jiǎn)介
移動(dòng)互聯(lián)網(wǎng)發(fā)展至今,以微信為首的即時(shí)通訊服務(wù)已經(jīng)融入了我們生活中的各個(gè)角落率拒,在公司的一些業(yè)務(wù)中也扮演著重要的角色崩泡,對(duì)于即時(shí)通訊我們公司原來(lái)是使用的環(huán)信的服務(wù),但是有很多定制化的需求無(wú)法實(shí)現(xiàn)猬膨,所以后來(lái)決定內(nèi)部開發(fā)一個(gè)滿足定制化需求的即時(shí)通訊微服務(wù)角撞。
使用socket.io
框架是因?yàn)楫?dāng)時(shí)后端缺人掘譬,加上看了一些例子后覺得使用起來(lái)真的很方便削罩,而且全平臺(tái)支持,所以這個(gè)微服務(wù)就在前端團(tuán)隊(duì)進(jìn)行落地實(shí)踐轴捎,目前效果還不錯(cuò)召耘。
社區(qū)目前這方面的內(nèi)容比較少或者太簡(jiǎn)陋(只有一個(gè)公共的聊天室這種)。另外就是在業(yè)務(wù)開發(fā)過程中被 PM 搞得很難受褐隆,所以想脫離一些特有的業(yè)務(wù)上的東西污它,實(shí)現(xiàn)一個(gè)功能簡(jiǎn)單五臟俱全的不摻雜公司業(yè)務(wù)的 IM 應(yīng)用,包含服務(wù)端,管理端和客戶端庶弃∩辣幔客戶端的模仿對(duì)象是微信,因?yàn)槲液苁煜ばィ挥迷诋a(chǎn)品上面思考太多固惯,另外就是試用的人很熟悉,不需要太多的溝通成本缴守。
框架簡(jiǎn)介
要開發(fā)一套完整的即時(shí)通訊服務(wù)葬毫,需要以下部分:
- 服務(wù)端:用來(lái)實(shí)現(xiàn)基礎(chǔ)的服務(wù)接口和數(shù)據(jù)持久化
- 客戶端:完成登錄镇辉、聊天等基礎(chǔ)功能,類似微信
- 管理端:管理群組贴捡、用戶和角色權(quán)限
server
為企業(yè)級(jí)框架和應(yīng)用而生
選用阿里的 egg.js 框架做支撐忽肛,看中的原因是他們內(nèi)部大規(guī)模的落地和安全方面做得比較好,沒有選擇 nest 的原因是集成 socket.io
比較麻煩烂斋,ORM 選用 sequelize屹逛,數(shù)據(jù)庫(kù)是 mysql ,之前一起使用過,上手難度小
admin
開箱即用的中臺(tái)前端/設(shè)計(jì)解決方案
選擇 Ant Design Pro 作為模板開發(fā)管理端汛骂,選用的原因是我對(duì) Vue 全家桶比較熟悉罕模,想借著這個(gè)機(jī)會(huì)熟悉下整套 React 生態(tài) 的開發(fā)流程,感受下目前國(guó)內(nèi)兩大開發(fā)框架的本質(zhì)區(qū)別和殊途同歸帘瞭,Ant Design Pro 已經(jīng)發(fā)布了好幾年了淑掌,也的確給中小型企業(yè)帶來(lái)效率的提升,也正好適合我這的需求图张。
client
??? Vue.js 開發(fā)的標(biāo)準(zhǔn)工具
使用 @vue/cli 搭建 IM 服務(wù)的客戶端锋拖,一個(gè)移動(dòng)端的 H5 項(xiàng)目,UI 框架使用的有贊 vant祸轮,集成了我的開源組件vue-page-stack和黃老師的better-scroll兽埃,實(shí)現(xiàn) IM 的基礎(chǔ)功能
實(shí)體關(guān)系
作為一個(gè)前端工程師,大多數(shù)的日常工作是不需要思考實(shí)體關(guān)系的适袜。但是柄错,就我的實(shí)際體驗(yàn)來(lái)看,懂得實(shí)體關(guān)系可以幫助我們更好的理解業(yè)務(wù)模型苦酱。而對(duì)產(chǎn)品和業(yè)務(wù)理解的提升對(duì)我們的幫助是非常大的售貌,可以在需求評(píng)審的時(shí)候發(fā)現(xiàn)很多不符合邏輯的地方(怎么又要吐槽產(chǎn)品經(jīng)理了),這時(shí)候能提出來(lái)就會(huì)主動(dòng)避免我們?cè)诤罄m(xù)的過程中進(jìn)行反復(fù)開發(fā)疫萤,同時(shí)可以和產(chǎn)品側(cè)的同學(xué)形成比較良好的互動(dòng)(而不是互懟)颂跨。下面簡(jiǎn)單羅列下比較重要的實(shí)體關(guān)系:
<img width="600" src="https://i.loli.net/2020/07/14/Zhz85V2ptOylDcj.png">
通過上圖可以看到 user 是整個(gè)關(guān)系圖中的核心,下面介紹下各個(gè)實(shí)體之間的關(guān)系:
- user 和 user_info(用戶信息) 是一對(duì)一的關(guān)系
- user 和 role(角色)是多對(duì)多的關(guān)系
- role 和 right(權(quán)限)是多對(duì)多的關(guān)系
- user 和 apply(申請(qǐng))是多對(duì)多的關(guān)系扯饶,申請(qǐng)都是涉及到兩個(gè) user(申請(qǐng)人和被申請(qǐng)人)
- user 和 group(群組)是多對(duì)多的關(guān)系
- group 和 conversation(會(huì)話) 是一對(duì)一的關(guān)系
- friend 和 conversation(會(huì)話) 是一對(duì)一的關(guān)系
- conversation 和 message(消息)是 1 對(duì)多的關(guān)系
- friend(好友關(guān)系) 和 user 沒有直接關(guān)系恒削,friend 由兩個(gè) user 確定
下面詳細(xì)介紹下會(huì)話、角色與權(quán)限:
會(huì)話
完成一個(gè)即時(shí)通訊應(yīng)用尾序,需要考慮的第一個(gè)事情就是會(huì)話钓丰,就是我們微信里面的對(duì)話窗口。思考會(huì)話和消息每币、用戶携丁、群組之間的關(guān)系花費(fèi)了不少的精力,最終形成以下的基本關(guān)系:
- 2 個(gè)用戶參與的聊天屬于建立了 Friend 關(guān)系(互為好友)
- 多個(gè)用戶參與的聊天組成了群組關(guān)系
- Friend 和會(huì)話之間的關(guān)系是 1 對(duì) 1 的關(guān)系兰怠,可以通過 Friend 找到此 Friend 的會(huì)話梦鉴,也可以通過會(huì)話確定 Friend
- 群組和會(huì)話之間的關(guān)系是 1 對(duì) 1 的關(guān)系李茫,可以通過群組找到此群組的會(huì)話,也可以通過會(huì)話確定群組
- 消息屬于某個(gè)會(huì)話尚揣,可以根據(jù)會(huì)話查看對(duì)應(yīng)的消息列表
- 保存消息的時(shí)候更新會(huì)話的激活時(shí)間涌矢,用戶的會(huì)話列表根據(jù)激活時(shí)間排序,也就是最近的會(huì)話再最前面
也就是說(shuō)快骗,用戶和會(huì)話沒有直接的關(guān)系娜庇,只能通過用戶對(duì)應(yīng)的單聊和群聊去獲取會(huì)話,這樣做可以有以下的好處:
- 無(wú)論是單聊還是群聊方篮,連接上的用戶只要 join 進(jìn)對(duì)應(yīng)的會(huì)話 room 里面就可以名秀,消息也是在對(duì)應(yīng)的 room 里面發(fā)布
- 無(wú)論是單聊還是群聊,消息的保存和查詢都比較簡(jiǎn)單藕溅,都是只針對(duì)這個(gè)會(huì)話
- 獲取個(gè)人的會(huì)話列表也變得很簡(jiǎn)單匕得,用戶的會(huì)話列表通過查詢用戶『所有的 Friend 和群組』->『所有的會(huì)話』->『排序會(huì)話(根據(jù)激活時(shí)間)』,就可以獲取
角色和權(quán)限
為了設(shè)計(jì)一個(gè)靈活巾表、通用汁掠、方便的權(quán)限管理系統(tǒng),本系統(tǒng)采用 RBAC(基于角色的訪問控制)控制集币,來(lái)設(shè)計(jì)一個(gè)通用的『用戶角色權(quán)限』平臺(tái)考阱,方便后期擴(kuò)展。
RBAC
RBAC(基于角色的訪問控制)是指用戶通過角色與權(quán)限進(jìn)行關(guān)聯(lián)鞠苟。即一個(gè)用戶擁有若干角色乞榨,每一個(gè)角色擁有若干權(quán)限(當(dāng)然了,別把沖突的角色和權(quán)限配在一起)当娱。這樣吃既,就構(gòu)造成“用戶—角色—權(quán)限”的授權(quán)模型。在這種模型中跨细,用戶與角色之間鹦倚、角色與權(quán)限之間,一般是多對(duì)多的關(guān)系冀惭。
本系統(tǒng)默認(rèn)的角色和權(quán)限
本系統(tǒng)默認(rèn)有管理員申鱼、一般用戶、禁言用戶和封禁用戶這幾種角色云头,給不同的角色分配不同的權(quán)限,所以需要針對(duì)管理和發(fā)言等接口路由做一下統(tǒng)一的鑒權(quán)(通過中間件的方式)處理淫半,具體方式和方法在后端項(xiàng)目中會(huì)詳細(xì)說(shuō)明溃槐。本系統(tǒng)暫時(shí)采用預(yù)先定義了角色和權(quán)限的方式,后續(xù)想要擴(kuò)展的話可以編輯角色和權(quán)限科吭。
管理員
沒見過微信的管理端昏滴,但是可以想象一下猴鲫,管理員可以配置用戶的角色和權(quán)限,可以編輯群組的狀態(tài):
- 登錄的權(quán)限
- 群組狀態(tài)的編輯
- 針對(duì)用戶的角色和權(quán)限的編輯
普通用戶
注冊(cè)登錄后谣殊,可以正常的添加好友和加入群組拂共,可以修改個(gè)人基礎(chǔ)信息和處理申請(qǐng)
- 注冊(cè)登錄
- 編輯個(gè)人基礎(chǔ)信息
- 添加好友,申請(qǐng)入群
- 處理好友申請(qǐng)和入群申請(qǐng)
- 聊天
禁言用戶
- 注冊(cè)登錄
- 編輯個(gè)人基礎(chǔ)信息
- 添加好友姻几,申請(qǐng)入群
- 處理好友申請(qǐng)和入群申請(qǐng)
封禁用戶
無(wú)法登錄
角色的組合
舉個(gè)例子:現(xiàn)在有一個(gè)新版的個(gè)人中心需要上線測(cè)試宜狐,首先新建一個(gè)角色『測(cè)試個(gè)人中心』,再給這個(gè)角色分配對(duì)應(yīng)的權(quán)限蛇捌;然后給普通用戶做個(gè)分組抚恒,選出一些人配置上這個(gè)角色,這樣就可以進(jìn)行測(cè)試了络拌。
即時(shí)通訊原理
下面說(shuō)下即時(shí)通訊服務(wù)的核心通訊原理俭驮,和一般的 http 服務(wù)一樣,有一個(gè)服務(wù)端和客戶端進(jìn)行通訊春贸,只不過詳細(xì)的協(xié)議和處理方式不一樣混萝。
WebSocket
由于歷史原因,現(xiàn)在主流的 http 協(xié)議是無(wú)狀態(tài)協(xié)議(HTTP2 暫時(shí)應(yīng)用不廣泛)萍恕,一般情況是由客戶端主動(dòng)發(fā)起請(qǐng)求逸嘀,然后服務(wù)端去響應(yīng)。那么為了實(shí)現(xiàn)服務(wù)端向客戶端推送信息雄坪,就需要前端主動(dòng)向后端去輪詢厘熟,這種方式低效且容易出錯(cuò),在之前我們的管理端首頁(yè)確實(shí)是這么做的(5s 一次)。
為了實(shí)現(xiàn)這種服務(wù)端主動(dòng)推送信息的需求维哈, HTML5 開始提供一種在單個(gè) TCP 連接上進(jìn)行全雙工通訊的協(xié)議绳姨,也就是 WebSocket。WebSocket 使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單阔挠,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)飘庄。WebSocket 協(xié)議在 2008 年誕生,2011 年成為國(guó)際標(biāo)準(zhǔn)购撼,目前絕大部分瀏覽器都已經(jīng)支持了跪削。
WebSocket 的用法相當(dāng)簡(jiǎn)單:
var ws = new WebSocket("wss://echo.websocket.org");
ws.onopen = function(evt) {
console.log("Connection open ...");
ws.send("Hello WebSockets!");
};
ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
ws.close();
};
ws.onclose = function(evt) {
console.log("Connection closed.");
};
有了 WebSocket 協(xié)議讓服務(wù)端主動(dòng)推送信息有了先進(jìn)的武器,那么有沒有什么方式可以兼容新舊瀏覽器呢迂求?其實(shí)很多人想到了這點(diǎn)碾盐,答案就是socket.io
socket.io
socket.io
進(jìn)一步封裝了WebSocket
的接口,而且可以在舊版本瀏覽器中自主切換到使用輪詢的方式進(jìn)行通訊(我們使用者是不會(huì)感知的)揩局,形成了一套統(tǒng)一的接口毫玖,大大減輕了開發(fā)的負(fù)擔(dān)。主要具有以下優(yōu)點(diǎn):
- 封裝出了一套非常易用的接口,前后端統(tǒng)一付枫,使用非常簡(jiǎn)單
- 全平臺(tái)支持(原生和 H5烹玉,微信小程序中也有對(duì)應(yīng)的實(shí)現(xiàn))
- 自適應(yīng)瀏覽器,在比較老的瀏覽器中主動(dòng)切換使用輪詢的方式阐滩,不需要我們自己搞輪詢
最快二打,最可靠的即時(shí)通訊引擎(FEATURING THE FASTEST AND MOST RELIABLE REAL-TIME ENGINE)
使用起來(lái)真的很簡(jiǎn)單:
var io = require('socket.io')(80);
var cfg = require('./config.json');
var tw = require('node-tweet-stream')(cfg);
tw.track('socket.io');
tw.track('javascript');
tw.on('tweet', function(tweet){
io.emit('tweet', tweet);
});
總結(jié)
有了以上的基礎(chǔ),我們就基本完成了開始寫代碼之前的準(zhǔn)備:明確了這個(gè)應(yīng)用的基礎(chǔ)功能和實(shí)體之間的關(guān)系掂榔,也明確了基礎(chǔ)的技術(shù)方案選型继效,劃分了3個(gè)項(xiàng)目的各自任務(wù)。下面就開始完成 server 端吧
未完待續(xù):下一篇介紹 server 端