1. 程式人生 > >im 系統架構問題

im 系統架構問題

1、啟動im專案的時候,所有的im節點都註冊到zkpath對應的 /im/gate節點,然後自己有iplist專案(tomcat)裡面維護著這些節點的資訊,然後每個節點如果有變化的時候,都會通知到所有的iplist,更新這些節點,同時iplist還會迴圈註冊watch,因為watch是一次性的,然後客戶端android,ios,web端呼叫iplist來通過roundrobin輪訓獲取節點資訊ip:port,然後返回給客戶端,以供客戶端發起長連線請求.

2、比如客戶端發了訊息,然後服務端返回過程中斷掉了網,出現了未傳送的紅點,這個時候如何確定保證唯一性,也就是不能發重複的訊息,去重?

ios和android都有一個唯一id生成功能,能夠保證去重

3、比如剛開始使用者a在 im1機器上面,突然間網路斷開了,等im1連線到了im2機器上面的時候這個時候使用者是和im1互動呢,還是和im2互動呢?

每個使用者和channel關係通過一個map<user, channel>維護在其中一臺機器上面,同時redis裡面還做了記錄Map<user, ip:port>,當用戶切換到了im2的時候,這個時候redis裡面記錄了兩條使用者對應的記錄,當用戶連線到了im2的時候,這個時候系統就會通過redis裡面的user對應的ip:port去呼叫一次im1伺服器,去把使用者和channel的關係給解除了.

4、空閒連線處理

由於ios切換到了後臺,就停止了和服務端的互動,然後android只要你登入了就會一直互動,redis記錄著每個使用者的最後一次聊天記錄資訊,然後如果十分鐘沒有聊天的話,就自動斷開連線,節省伺服器無畏的開銷

5、訊息由於使用者端網路不好沒有推送成功

5.1、使用者A斷線重連始終連線的是同一臺伺服器

A發訊息給B,這個時候,使用者A會先發給服務端,然後服務端開始推送,如果服務端推送的過程中,使用者和服務端的網路斷開了的話,那麼這個時候A傳送的訊息就到達不了B,這個時候就等待下次使用者A登入的時候去拉取。

5.2、使用者A斷線重連的是不同的伺服器

A發訊息給B,這個時候,使用者A會先發給服務端,然後服務端開始推送,如果服務端推送的過程中,使用者和服務端的網路斷開了的話,那麼這個時候A傳送的訊息就到達不了B,這個時候就等待下次使用者A登入的時候去拉取,如果A登入到了不同的伺服器的話,那麼這個時候首先檢測redis裡面有沒有更多的登入記錄,有的話,就獲取到上次登入的Map<user, ip:port>,然後呼叫對應的機器裡面儲存的map<user, channel>關係,然後就把當前的登入使用者和ip:port記錄進去,然後去聊天記錄表拉取對應的未讀訊息返回給使用者端。

6、使用者登入

伺服器端登入資訊驗證成功後生成String型別的Token(使用者id+時間戳+隨機數,有效期一週)返回給客戶端,此Token用於斷線重連的驗證資訊

開啟心跳檢測,客戶端每空閒5s傳送一個心跳包,伺服器端每空閒6s計一次心跳失敗

username和channel維護在一個Map集合中

7、斷線重連

使用Token嘗試重連,然後做後面的其他未讀訊息,之類的校驗以及處理

8、專案啟動順序: