「實(shí)戰(zhàn)」搭建完整的IM(即時(shí)通訊)應(yīng)用(1)

介紹

即時(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)介

  1. 注冊(cè),登錄馋艺,個(gè)人栅干、群組聊天,個(gè)人信息編輯等基礎(chǔ)功能
  2. 申請(qǐng)?zhí)砑雍糜押蜕暾?qǐng)入群
  3. 表情捐祠,圖片碱鳞,視頻,定位信息支持
  4. 聊天會(huì)話列表記錄
  5. 消息記錄(微信的消息記錄真實(shí)一言難盡)
  6. 支持多點(diǎn)同時(shí)登錄
  7. 百度 UNIT 機(jī)器人自動(dòng)回復(fù)(todo)
  8. 管理端踱蛀,進(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ù)葬毫,需要以下部分:

  1. 服務(wù)端:用來(lái)實(shí)現(xiàn)基礎(chǔ)的服務(wù)接口和數(shù)據(jù)持久化
  2. 客戶端:完成登錄镇辉、聊天等基礎(chǔ)功能,類似微信
  3. 管理端:管理群組贴捡、用戶和角色權(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)系:

  1. user 和 user_info(用戶信息) 是一對(duì)一的關(guān)系
  2. user 和 role(角色)是多對(duì)多的關(guān)系
  3. role 和 right(權(quán)限)是多對(duì)多的關(guān)系
  4. user 和 apply(申請(qǐng))是多對(duì)多的關(guān)系扯饶,申請(qǐng)都是涉及到兩個(gè) user(申請(qǐng)人和被申請(qǐng)人)
  5. user 和 group(群組)是多對(duì)多的關(guān)系
  6. group 和 conversation(會(huì)話) 是一對(duì)一的關(guān)系
  7. friend 和 conversation(會(huì)話) 是一對(duì)一的關(guān)系
  8. conversation 和 message(消息)是 1 對(duì)多的關(guān)系
  9. 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)系:

  1. 2 個(gè)用戶參與的聊天屬于建立了 Friend 關(guān)系(互為好友)
  2. 多個(gè)用戶參與的聊天組成了群組關(guān)系
  3. Friend 和會(huì)話之間的關(guān)系是 1 對(duì) 1 的關(guān)系兰怠,可以通過 Friend 找到此 Friend 的會(huì)話梦鉴,也可以通過會(huì)話確定 Friend
  4. 群組和會(huì)話之間的關(guān)系是 1 對(duì) 1 的關(guān)系李茫,可以通過群組找到此群組的會(huì)話,也可以通過會(huì)話確定群組
  5. 消息屬于某個(gè)會(huì)話尚揣,可以根據(jù)會(huì)話查看對(duì)應(yīng)的消息列表
  6. 保存消息的時(shí)候更新會(huì)話的激活時(shí)間涌矢,用戶的會(huì)話列表根據(jù)激活時(shí)間排序,也就是最近的會(huì)話再最前面

也就是說(shuō)快骗,用戶和會(huì)話沒有直接的關(guān)系娜庇,只能通過用戶對(duì)應(yīng)的單聊和群聊去獲取會(huì)話,這樣做可以有以下的好處:

  1. 無(wú)論是單聊還是群聊方篮,連接上的用戶只要 join 進(jìn)對(duì)應(yīng)的會(huì)話 room 里面就可以名秀,消息也是在對(duì)應(yīng)的 room 里面發(fā)布
  2. 無(wú)論是單聊還是群聊,消息的保存和查詢都比較簡(jiǎn)單藕溅,都是只針對(duì)這個(gè)會(huì)話
  3. 獲取個(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):

  1. 登錄的權(quán)限
  2. 群組狀態(tài)的編輯
  3. 針對(duì)用戶的角色和權(quán)限的編輯

普通用戶

注冊(cè)登錄后谣殊,可以正常的添加好友和加入群組拂共,可以修改個(gè)人基礎(chǔ)信息和處理申請(qǐng)

  1. 注冊(cè)登錄
  2. 編輯個(gè)人基礎(chǔ)信息
  3. 添加好友,申請(qǐng)入群
  4. 處理好友申請(qǐng)和入群申請(qǐng)
  5. 聊天

禁言用戶

  1. 注冊(cè)登錄
  2. 編輯個(gè)人基礎(chǔ)信息
  3. 添加好友姻几,申請(qǐng)入群
  4. 處理好友申請(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)支持了跪削。

image

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):

  1. 封裝出了一套非常易用的接口,前后端統(tǒng)一付枫,使用非常簡(jiǎn)單
  2. 全平臺(tái)支持(原生和 H5烹玉,微信小程序中也有對(duì)應(yīng)的實(shí)現(xiàn))
  3. 自適應(yīng)瀏覽器,在比較老的瀏覽器中主動(dòng)切換使用輪詢的方式阐滩,不需要我們自己搞輪詢

這是 socket.io 主頁(yè)

最快二打,最可靠的即時(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 端

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末衅疙,一起剝皮案震驚了整個(gè)濱河市莲趣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饱溢,老刑警劉巖喧伞,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異绩郎,居然都是意外死亡潘鲫,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門肋杖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)溉仑,“玉大人,你說(shuō)我怎么就攤上這事状植∽蔷梗” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵津畸,是天一觀的道長(zhǎng)振定。 經(jīng)常有香客問我,道長(zhǎng)肉拓,這世上最難降的妖魔是什么后频? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮暖途,結(jié)果婚禮上卑惜,老公的妹妹穿的比我還像新娘。我一直安慰自己驻售,他們只是感情好露久,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著欺栗,像睡著了一般抱环。 火紅的嫁衣襯著肌膚如雪壳快。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天镇草,我揣著相機(jī)與錄音,去河邊找鬼瘤旨。 笑死梯啤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的存哲。 我是一名探鬼主播因宇,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼祟偷!你這毒婦竟也來(lái)了察滑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤修肠,失蹤者是張志新(化名)和其女友劉穎贺辰,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嵌施,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡饲化,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吗伤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吃靠。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖足淆,靈堂內(nèi)的尸體忽然破棺而出巢块,到底是詐尸還是另有隱情,我是刑警寧澤巧号,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布族奢,位于F島的核電站,受9級(jí)特大地震影響裂逐,放射性物質(zhì)發(fā)生泄漏歹鱼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一卜高、第九天 我趴在偏房一處隱蔽的房頂上張望弥姻。 院中可真熱鬧,春花似錦掺涛、人聲如沸庭敦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)秧廉。三九已至伞广,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間疼电,已是汗流浹背嚼锄。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蔽豺,地道東北人区丑。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像修陡,于是被迫代替她去往敵國(guó)和親沧侥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355