移動IM開發指南3:如何優化登入模組

網易雲信發表於2018-06-22
《移動IM開發指南》系列文章將會介紹一個IM APP的方方面面,包括技術選型、登陸優化等。此外,本文作者會結合他在網易雲信多年iOS IM SDK開發的經驗,深度分析實際開發中的各種常見問題。

推薦閱讀

移動IM開發指南1:如何進行技術選型

移動IM開發指南2:心跳指令詳解


在移動 IM 模組中,最核心最複雜的模組莫過於登入模組。一個沒有經過很好優化的登入模組往往耗時久且浪費流量:一次登入短則數十秒,長則幾分鐘,同時同步下幾百 KB 甚至幾M的資料。

一個簡單的登入步驟可以分為如下幾步:

  • 請求 lbs
  • 連線 link
  • 收發登入請求
  • 同步 IM 資料

而這裡的每一步都是有優化的可能性。(事實上下面的很多思路都是普適的,不是隻有 IM APP 才用得到)

優化 lbs 請求

在 PC 時代,我們往往將請求 lbs 和連線伺服器做一個串聯,畢竟只有先請求完畢 lbs 才能夠拿到真正的 link 伺服器地址,從而進行連線操作。在具體操作上,一般 lbs 請求就是一次 HTTP 請求,這裡的耗時可想而知。所以一個樸素的優化想法就是從登入流程中移除這個環節。

然而直接粗暴去除 lbs 請求並不可取,如果我們直接內建域名或 ip,帶來最大問題自然是無法做負載均衡。所以更推薦將 lbs 請求非同步化:不在登入時做 lbs 請求,而在網路空閒和發生變化時進行請求並快取,每次登入則直接從本地快取獲取 link 地址。

DNS 優化

使用 TCP 時不可避免會碰到 DNS 解析的問題,畢竟我們不可能一直使用 IP 作為伺服器地址。在 PC 時代,DNS 解析幾乎不費事。但進入無線時代後,DNS 相關問題越來越嚴重。一方面,在行動網路下,DNS 解析速度無比龜速,一次 DNS 解析的時間甚至能趕上一次 TCP 連線的時間,幾秒,十幾秒,甚至三,四十秒的請求時間都很常見。另一方面,由於運營商的不作為和作為,行動網路下 DNS 也呈現瞭解析準確度低和經常被劫持的狀態。

針對這些情況可以考慮使用 HTTP DNS,github 也有很多開源的實現,比如HttpDNSLib。而最激進的方法自然是像前面優化 lbs 一樣,在個個環節中避免 DNS 解析:

  • lbs 返回伺服器 ip 而非域名
  • 本地快取 lbs ip 地址備用,請求 lbs 時優先使用 ip 而非域名

這種方式不僅可以避免 DNS 請求的耗時,也可以一定程度上規避 DNS 被劫持的問題。而弊端是針對這種情況需要在客戶端考慮一系列的其他問題:如何從 ip list 選擇有效地址,確定重新請求時機,負載均衡,節約流量等。

登入請求

事實上,登入請求環節其實並沒有多大的優化空間。一旦你連線上了伺服器,接下去要做的事無非是加密當前連線和傳送並接收登入反饋。這兩步缺一不可。而如何優化又往往會和具體的業務相關:假如我們使用類似於 HTTPS 一般的三步協商的加密流程,安全性的確可以得到保證,但是一來一回的次數過多,整個登入耗時就會增加。取巧的方法自然是將加密和登入請求合併,而這往往會涉及到對登入請求的改造。

同步策略優化

登入完畢後,客戶端需要從伺服器同步,一個常規的 IM APP 需要同步如下資料:

  • 好友列表
  • 好友個人資訊
  • 群組列表
  • 群成員列表
  • 群成員個人資訊
  • 離線訊息

假設一個使用者有 1000 個好友, 20 個 50 人群,平均每一項大約 200 個位元組,那麼一次全同步大約需要 0.2 * (1000 + 1000 + 20 + 1000 * 2) = 800 KB 的資料,這對於一個移動 IM 是無法接受的,更何況這還是一個較輕度使用者的資料量。

顯然全同步是無法接受的,改進的方法自然是按時間戳同步。客戶端永遠只更新比本地快取資料新的資料。這是一個常規的優化方向,還有一些根據業務需求可以實施的優化:延遲更新和按需更新。以群成員個人資訊為例,其實使用者並不關心其實時性,畢竟這些群成員並不一定是使用者好友,他們的資訊變動完全可以在使用者進行檢視時再更新(微信的策略)。而好友個人資訊也是同理,對於大部分介面而言,他們只關心使用者 Id,頭像和暱稱這三個基礎資訊,而一些錦上添花的 Profile 資訊完全可以在使用者檢視相應介面時進行一次按時間戳的更新。

以上就是網易雲信對於登入模組優化的介紹,更多幹貨和技術文章請移步網易雲信部落格


相關文章