日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

im即时通讯源码+软件+app附详细封装视频搭建教程

發(fā)布時(shí)間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 im即时通讯源码+软件+app附详细封装视频搭建教程 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

FEIIM一款面向開(kāi)發(fā)者的?IM(即時(shí)通訊)系統(tǒng);同時(shí)提供了一些組件幫助開(kāi)發(fā)者構(gòu)建一款屬于自己可水平擴(kuò)展的?IM?。尾部下載完整版PHP即時(shí)通訊源碼)

借助?FEIIM?你可以實(shí)現(xiàn)以下需求:

  • IM?即時(shí)通訊系統(tǒng)。
  • 適用于?APP?的消息推送中間件。
  • IOT?海量連接場(chǎng)景中的消息透?jìng)髦虚g件。

演示

本次主要涉及到 IM 即時(shí)通訊,所以特地截了很多演示圖。

?

?

?

架構(gòu)設(shè)計(jì)

下面來(lái)看看具體的架構(gòu)設(shè)計(jì)。

  • FEIIM?中的各個(gè)組件均采用?SpringBoot?構(gòu)建。
  • 采用?Netty + Google Protocol Buffer?構(gòu)建底層通信。
  • Redis?存放各個(gè)客戶端的路由信息、賬號(hào)信息、在線狀態(tài)等。
  • Zookeeper?用于?IM-server?服務(wù)的注冊(cè)與發(fā)現(xiàn)。

整體主要由以下模塊組成:

cim-server

IM?服務(wù)端;用于接收?client?連接、消息透?jìng)鳌⑾⑼扑偷裙δ堋?/p>

支持集群部署。

cim-forward-route

消息路由服務(wù)器;用于處理消息路由、消息轉(zhuǎn)發(fā)、用戶登錄、用戶下線以及一些運(yùn)營(yíng)工具(獲取在線用戶數(shù)等)。

cim-client

IM?客戶端;給用戶使用的消息終端,一個(gè)命令即可啟動(dòng)并向其他人發(fā)起通訊(群聊、私聊);同時(shí)內(nèi)置了一些常用命令方便使用。

流程圖

整體的流程也比較簡(jiǎn)單,流程圖如下:

  • 客戶端向?route?發(fā)起登錄。
  • 登錄成功從?Zookeeper?中選擇可用?IM-server?返回給客戶端,并保存登錄、路由信息到?Redis。
  • 客戶端向?IM-server?發(fā)起長(zhǎng)連接,成功后保持心跳。
  • 客戶端下線時(shí)通過(guò)?route?清除狀態(tài)信息。

所以當(dāng)我們自己部署時(shí)需要以下步驟:

  • 搭建基礎(chǔ)中間件?Redis、Zookeeper。
  • 部署?cim-server,這是真正的 IM 服務(wù)器,為了滿足性能需求所以支持水平擴(kuò)展,只需要注冊(cè)到同一個(gè)?Zookeeper?即可。
  • 部署?cim-forward-route,這是路由服務(wù)器,所有的消息都需要經(jīng)過(guò)它。由于它是無(wú)狀態(tài)的,所以也可以利用?Nginx?代理提高可用性。
  • cim-client?真正面向用戶的客戶端;啟動(dòng)之后會(huì)自動(dòng)連接 IM 服務(wù)器便可以在控制臺(tái)收發(fā)消息了。

更多使用介紹可以參考快速啟動(dòng)。

詳細(xì)設(shè)計(jì)

接下來(lái)重點(diǎn)看看具體的實(shí)現(xiàn),比如群聊、私聊消息如何流轉(zhuǎn);IM 服務(wù)端負(fù)載均衡;服務(wù)如何注冊(cè)發(fā)現(xiàn)等等。

IM 服務(wù)端

先來(lái)看看服務(wù)端;主要是實(shí)現(xiàn)客戶端上下線、消息下發(fā)等功能。

首先是服務(wù)啟動(dòng):

由于是在?SpringBoot?中搭建的,所以在應(yīng)用啟動(dòng)時(shí)需要啟動(dòng)?Netty?服務(wù)。

從?pipline?中可以看出使用了?Protobuf?的編解碼(具體報(bào)文在客戶端中分析)。

注冊(cè)發(fā)現(xiàn)

需要滿足?IM?服務(wù)端的水平擴(kuò)展需求,所以?cim-server?是需要將自身數(shù)據(jù)發(fā)布到注冊(cè)中心的。

這里參考之前分享的《搞定服務(wù)注冊(cè)與發(fā)現(xiàn)》有具體介紹。

所以在應(yīng)用啟動(dòng)成功后需要將自身數(shù)據(jù)注冊(cè)到?Zookeeper?中。

最主要的目的就是將當(dāng)前應(yīng)用的?ip + cim-server-port+ http-port?注冊(cè)上去。

上圖是我在演示環(huán)境中注冊(cè)的兩個(gè)?cim-server?實(shí)例(由于在一臺(tái)服務(wù)器,所以只是端口不同)。

這樣在客戶端(監(jiān)聽(tīng)這個(gè)?Zookeeper?節(jié)點(diǎn))就能實(shí)時(shí)的知道目前可用的服務(wù)信息。

登錄

當(dāng)客戶端請(qǐng)求?cim-forward-route?中的登錄接口(詳見(jiàn)下文)做完業(yè)務(wù)驗(yàn)證(就相當(dāng)于日常登錄其他網(wǎng)站一樣)之后,客戶端會(huì)向服務(wù)端發(fā)起一個(gè)長(zhǎng)連接,如之前的流程所示:

這時(shí)客戶端會(huì)發(fā)送一個(gè)特殊報(bào)文,表明當(dāng)前是登錄信息。

服務(wù)端收到后就需要將該客戶端的?userID?和當(dāng)前?Channel?通道關(guān)系保存起來(lái)。

同時(shí)也緩存了用戶的信息,也就是?userID?和 用戶名。

離線

當(dāng)客戶端斷線后也需要將剛才緩存的信息清除掉。

同時(shí)也需要調(diào)用?route?接口清除相關(guān)信息(具體接口看下文)。

IM 路由

從架構(gòu)圖中可以看出,路由層是非常重要的一環(huán);它提供了一系列的?HTTP?服務(wù)承接了客戶端和服務(wù)端。

目前主要是以下幾個(gè)接口。

注冊(cè)接口

由于每一個(gè)客戶端都是需要登錄才能使用的,所以第一步自然是注冊(cè)。

這里就設(shè)計(jì)的比較簡(jiǎn)單,直接利用?Redis?來(lái)存儲(chǔ)用戶信息;用戶信息也只有?ID?和?userName?而已。

只是為了方便查詢?cè)?Redis?中的?KV?又反過(guò)來(lái)存儲(chǔ)了一份?VK,這樣?ID?和?userName?都必須唯一。

登錄接口

這里的登錄和?cim-server?中的登錄不一樣,具有業(yè)務(wù)性質(zhì),

  • 登錄成功之后需要判斷是否是重復(fù)登錄(一個(gè)用戶只能運(yùn)行一個(gè)客戶端)。
  • 登錄成功后需要從?Zookeeper?中獲取服務(wù)列表(cim-server)并根據(jù)某種算法選擇一臺(tái)服務(wù)返回給客戶端。
  • 登錄成功之后還需要保存路由信息,也就是當(dāng)前用戶分配的服務(wù)實(shí)例保存到?Redis?中。

為了實(shí)現(xiàn)只能一個(gè)用戶登錄,使用了?Redis?中的?set?來(lái)保存登錄信息;利用?userID?作為?key?,重復(fù)的登錄就會(huì)寫入失敗。

類似于 Java 中的 HashSet,只能去重保存。

獲取一臺(tái)可用的路由實(shí)例也比較簡(jiǎn)單:

  • 先從?Zookeeper?獲取所有的服務(wù)實(shí)例做一個(gè)內(nèi)部緩存。
  • 輪詢選擇一臺(tái)服務(wù)器(目前只有這一種算法,后續(xù)會(huì)新增)。

當(dāng)然要獲取?Zookeeper?中的服務(wù)實(shí)例前自然是需要監(jiān)聽(tīng)?cim-server?之前注冊(cè)上去的那個(gè)節(jié)點(diǎn)。

具體代碼如下:


?

也是在應(yīng)用啟動(dòng)之后監(jiān)聽(tīng)?Zookeeper?中的路由節(jié)點(diǎn),一旦發(fā)生變化就會(huì)更新內(nèi)部緩存。

這里使用的是 Guava 的 cache,它基于?ConcurrentHashMap,所以可以保證清除、新增緩存的原子性。

群聊接口

這是一個(gè)真正發(fā)消息的接口,實(shí)現(xiàn)的效果就是其中一個(gè)客戶端發(fā)消息,其余所有客戶端都能收到!

流程肯定是客戶端發(fā)送一條消息到服務(wù)端,服務(wù)端收到后在上文介紹的?SessionSocketHolder?中遍歷所有?Channel(通道)然后下發(fā)消息即可。

服務(wù)端是單機(jī)倒也可以,但現(xiàn)在是集群設(shè)計(jì)。所以所有的客戶端會(huì)根據(jù)之前的輪詢算法分配到不同的?cim-server?實(shí)例中。

因此就需要路由層來(lái)發(fā)揮作用了。

路由接口收到消息后首先遍歷出所有的客戶端和服務(wù)實(shí)例的關(guān)系。

路由關(guān)系在?Redis?中的存放如下:

由于?Redis?單線程的特質(zhì),當(dāng)數(shù)據(jù)量大時(shí);一旦使用 keys 匹配所有?cim-route:*?數(shù)據(jù),會(huì)導(dǎo)致 Redis 不能處理其他請(qǐng)求。

所以這里改為使用 scan 命令來(lái)遍歷所有的?cim-route:*。


接著會(huì)挨個(gè)調(diào)用每個(gè)客戶端所在的服務(wù)端的?HTTP?接口用于推送消息。

在?cim-server?中的實(shí)現(xiàn)如下:

cim-server?收到消息后會(huì)在內(nèi)部緩存中查詢?cè)?userID 的通道,接著只需要發(fā)消息即可。

在線用戶接口

這是一個(gè)輔助接口,可以查詢出當(dāng)前在線用戶信息。

實(shí)現(xiàn)也很簡(jiǎn)單,也就是查詢之前保存 ”用戶登錄狀態(tài)的那個(gè)去重?set?“即可。

私聊接口

之所以說(shuō)獲取在線用戶是一個(gè)輔助接口,其實(shí)就是用于輔助私聊使用的。

一般我們使用私聊的前提肯定得知道當(dāng)前哪些用戶在線,接著你才會(huì)知道你要和誰(shuí)進(jìn)行私聊。

類似于這樣:

在我們這個(gè)場(chǎng)景中,私聊的前提就是需要獲得在線用戶的?userID。

所以私聊接口在收到消息后需要查詢到接收者所在的?cim-server?實(shí)例信息,后續(xù)的步驟就和群聊一致了。調(diào)用接收者所在實(shí)例的?HTTP?接口下發(fā)信息。

只是群聊是遍歷所有的在線用戶,私聊只發(fā)送一個(gè)的區(qū)別。

下線接口

一旦客戶端下線,我們就需要將之前存放在?Redis?中的一些信息刪除掉(路由信息、登錄狀態(tài))。

IM 客戶端

客戶端中的一些邏輯其實(shí)在上文已經(jīng)談到一些了。

登錄

第一步也就是登錄,需要在啟動(dòng)時(shí)調(diào)用?route?的登錄接口,獲得?cim-server?信息再創(chuàng)建連接。

登錄過(guò)程中?route?接口會(huì)判斷是否為重復(fù)登錄,重復(fù)登錄則會(huì)直接退出程序。

接下來(lái)是利用?route?接口返回的?cim-server?實(shí)例信息(ip+port)創(chuàng)建連接。

最后一步就是發(fā)送一個(gè)登錄標(biāo)志的信息到服務(wù)端,讓它保持客戶端和?Channel?的關(guān)系。

自定義協(xié)議

上文提到的一些登錄報(bào)文、真正的消息報(bào)文這些其實(shí)都是在我們自定義協(xié)議中可以區(qū)別出來(lái)的。

由于是使用?Google Protocol Buffer?編解碼,所以先看看原始格式。

其實(shí)這個(gè)協(xié)議中目前一共就三個(gè)字段:

  • requestId?可以理解為?userId。
  • reqMsg?就是真正的消息。
  • type?也就是上文提到的消息類別。

目前主要是三種類型,分別對(duì)應(yīng)不同的業(yè)務(wù):

心跳

為了保持客戶端和服務(wù)端的連接,每隔一段時(shí)間沒(méi)有發(fā)送消息都需要自動(dòng)的發(fā)送心跳。

目前的策略是每隔一分鐘就是發(fā)送一個(gè)心跳包到服務(wù)端:

這樣服務(wù)端每隔一分鐘沒(méi)有收到業(yè)務(wù)消息時(shí)就會(huì)收到?ping?的心跳包:

內(nèi)置命令

客戶端也內(nèi)置了一些基本命令來(lái)方便使用。

命令描述
:q退出客戶端
:olu獲取所有在線用戶信息
:all獲取所有命令
:更多命令正在開(kāi)發(fā)中。。

比如輸入?:q?就會(huì)退出客戶端,同時(shí)會(huì)關(guān)閉一些系統(tǒng)資源。

當(dāng)輸入?:olu(onlineUser?的簡(jiǎn)寫)就會(huì)去調(diào)用?route?的獲取所有在線用戶接口。

群聊

群聊的使用非常簡(jiǎn)單,只需要在控制臺(tái)輸入消息回車即可。

這時(shí)會(huì)去調(diào)用?route?的群聊接口。

私聊

私聊也是同理,但前提是需要觸發(fā)關(guān)鍵字;使用?userId;;消息內(nèi)容?這樣的格式才會(huì)給某個(gè)用戶發(fā)送消息,所以一般都需要先使用?:olu?命令獲取所以在線用戶才方便使用。

消息回調(diào)

為了滿足一些定制需求,比如消息需要保存之類的。

所以在客戶端收到消息之后會(huì)回調(diào)一個(gè)接口,在這個(gè)接口中可以自定義實(shí)現(xiàn)。

因此先創(chuàng)建了一個(gè)?caller?的?bean,這個(gè)?bean?中包含了一個(gè)?CustomMsgHandleListener?接口,需要自行處理只需要實(shí)現(xiàn)此接口即可。

自定義界面

由于我自己不怎么會(huì)寫界面,但保不準(zhǔn)有其他大牛會(huì)寫。所以客戶端中的群聊、私聊、獲取在線用戶、消息回調(diào)等業(yè)務(wù)(以及之后的業(yè)務(wù))都是以接口形式提供。

也方便后面做頁(yè)面集成,只需要調(diào)這些接口就行了;具體實(shí)現(xiàn)不用怎么關(guān)心。

源碼打包

源碼以本文演示圖片為準(zhǔn)。

下載地址:https://yfi.lanzouj.com/iMJVn06qfq8h

總結(jié)

以上是生活随笔為你收集整理的im即时通讯源码+软件+app附详细封装视频搭建教程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。