《移動IM開發指南》系列文章將會介紹一個IM APP的方方面面,包括技術選型、登錄優化等。此外,本文做者會結合他在網易雲信多年iOS IM SDK開發的經驗,深度分析實際開發中的各類常見問題。git
推薦閱讀github
移動IM開發指南1:如何進行技術選型緩存
移動IM開發指南2:心跳指令詳解安全
在移動 IM 模塊中,最核心最複雜的模塊莫過於登陸模塊。一個沒有通過很好優化的登陸模塊每每耗時久且浪費流量:一次登陸短則數十秒,長則幾分鐘,同時同步下幾百 KB 甚至幾M的數據。服務器
一個簡單的登陸步驟能夠分爲以下幾步:微信
- 請求 lbs
- 鏈接 link
- 收發登陸請求
- 同步 IM 數據
而這裏的每一步都是有優化的可能性。(事實上下面的不少思路都是普適的,不是隻有 IM APP 才用獲得)網絡
優化 lbs 請求負載均衡
在 PC 時代,咱們每每將請求 lbs 和鏈接服務器作一個串聯,畢竟只有先請求完畢 lbs 纔可以拿到真正的 link 服務器地址,從而進行鏈接操做。在具體操做上,通常 lbs 請求就是一次 HTTP 請求,這裏的耗時可想而知。因此一個樸素的優化想法就是從登陸流程中移除這個環節。異步
然而直接粗暴去除 lbs 請求並不可取,若是咱們直接內置域名或 ip,帶來最大問題天然是沒法作負載均衡。因此更推薦將 lbs 請求異步化:不在登陸時作 lbs 請求,而在網絡空閒和發生變化時進行請求並緩存,每次登陸則直接從本地緩存獲取 link 地址。ide
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 信息徹底能夠在用戶查看相應界面時進行一次按時間戳的更新。