1. 程式人生 > >移動網際網路的架構設計淺談一

移動網際網路的架構設計淺談一

一,圖片體驗的優化。
       在手機上顯示圖片,速度是一個非常重要的體驗點,試想,如果您開啟一個網站,發現裡面的圖片一直顯示失敗或者是x,稍微做得好一點的,可能是一個不消失的loading或者是菊花等等,但不管如何, 沒能快速的拉取和展示圖片對使用者體驗是一個極大的挑戰。那麼,手機上的圖片體驗如何做呢?這裡筆者有些小總結:
    1,減少圖片的大小。在失真度和圖片大小中做好折衷,儘量利用工具減少圖片的size,也可以考慮利用不同的圖片格式。
    2,減少圖片的請求數。可以考慮把多個圖片利用類似css sprite的方式進行合併,這樣可以載入一次即可;
    3,考慮快取。對圖片在客戶端進行一定的快取,設定好快取時長和更新機制;
    4,考慮使用cdn進行載入圖片,做到就近接入訪問;
    5,解決DSN劫持的問題。在手機業務上的經驗告訴我們,很可能某些地區,某些運營商把我們的域名封掉或者劫持了,這樣,圖片的域名解釋出來的IP卻不是我們提供圖片服務的IP,並且這種情況很難發現,  因為,如果運營商通過抽樣隨機劫持,就很難發現。解決辦法可以:

 .去掉dns,改成直接訪問IP的方式,但需要解決根據使用者的ip獲取最近圖片服務的ip地址,實現上:這裡cgi在吐出訪問圖片的地址的時候,獲取使用者的來源閘道器IP,呼叫IP地址庫判斷來源IP所屬地和運營商,然後下發對應的圖片部署接入IP, 客戶端使用IP直連圖片伺服器,快速的訪問資源。

  問題是,有實現成本,得業務自己去實現類似一個dns解釋的邏輯,特別是圖片放到cdn的話,這樣改造就無法使用cdn帶來的加速服務能力。

 .做好dns劫持的監控,實際上圖片dns解釋到的vip list肯定是在我們的一個白名單內,如果不是,則肯定屬於dns劫持,客戶端可以在某個時候拉取一下我們的vip list,作為監控和判斷是否dns劫持的問題,如果dns的ip地址 不在白名單內,則替換使用白名單內的ip進行訪問。
  

 .考慮備用域名的方式,即如果一個域名拉取不到,改用備用域名進行訪問,當然如果備用域名也被劫持,那就不行了。

   6,不用圖片,考慮文字替代方案。
   
二,優化後臺的架構

     後臺返回越快,前端的體驗就越好,因此,也需要對後臺服務的呼叫鏈進行梳理,避免迴圈呼叫,快慢混雜等問題,基本的原則比較簡單,都是一些設計方面的原則
   1,輕重分離。服務中把訪問量大,需要速度快的服務和訪問量小,但業務邏輯複雜的流程從程式碼實現和物理部署上進行徹底分離,如用的接入cgi(甚至不同的域名),不同的後臺server,不同的叢集進行隔離。
      如果放在一起,慢的會拖住快的,這就像木桶原理一樣,最終的速度是由最慢的決定的,如果處理不好,可能導致整個服務堵塞不可用。
 
   2,評估好業務的訪問流程和路徑設計,區分關鍵路徑和非關鍵路徑,設計上儘量考慮把關鍵路徑轉換為非關鍵路徑,關鍵路徑需要有多級容災的考慮,非關鍵異常需要有監控。
   
   3,考慮非同步化。非同步化相比同步的實現來說稍微複雜一些,或者說需要做的工作可能多些,但非同步化的好處也會非常明顯,特別是需要高效能的業務流程。常見的非同步化實現策略是藉助mq作為各個系統的緩衝, 生產者程序或者子系統把訊息寫入mq即可立即返回,而消費者程序或者子系統則定時從mq讀取訊息繼續處理,並且把處理的結果通過回撥通知或者寫入返回mq給到生產者查詢。當然,如果生產者是不關注結果的,那 就更加簡單了,丟到mq後即可,這裡的問題是整個mq是整個業務流程的關鍵,需要確保服務的高度可用和效能。
 
   4,一些配置的動態載入,本地化儲存,加上基於版本的更新機制。筆者也發現過有些業務cgi之所以在較少請求量的時候就出現了較高的負載,最終不得不用更多的機器來承擔相應的請求量,定位最終原因是cgi在啟動的時候需要載入 很多配置的東西,甚至很多配置並不是該cgi需要的,優化思路是:是按需載入,只加載該cgi需要的;提前載入配置到共享記憶體,同時增加版本號,維護好cgi自身程序的私有版本和共享記憶體的版本,cgi啟動的時候比較版本號,發現不同,則 真正進行檔案的重新Load到記憶體。還有一種模式是採用配置中心進行推送的模式,實現集中管理。
 
   5,做好外部依賴的管理。一個業務流程可能往往要呼叫到外部的系統,並且這些系統可能不是你們團隊維護的,如果該系統是非關鍵路徑還好,如果是關鍵路徑,那麼做好對外部依賴的管理就顯得更加重要了,那麼如何做好外部依賴的管理呢?
      這裡有幾個小的tips:

 . 對外部呼叫的服務單獨進行封裝,如設計單獨的proxy去呼叫外部的服務,這樣的好處是方便集中監控和容災邏輯等處理,在設計上把外部因素進行物理隔離的第一步,後續如果外部系統的協議或者ip地址得發生變化,則可以只修改該模組即可 快速修復;

 . 嚴重建議對外部介面進行錯誤和超時的監控,一旦出問題,提前預警並快速解決,這裡是有血的教訓的,某業務和某平臺提供者雙方在糾結是誰的問題上吵得不可開交,不知道是誰的問題,業務說自己沒問題,平臺方說自己的服務也很快,如果 你能夠拿出你的監控資料,介面超時設定是 1s, 超時的記錄有n條,時間是ns,錯誤的記錄有m條,主要錯誤型別是xxx,那對快速定位是非常有幫助的。

 . 考慮是否可以弱化為非關鍵路徑?有些呼叫可能是否無法弱化為非關鍵路徑的,如登入態校驗,失敗了只能是業務流程終止,給使用者返回失敗(當然可能存在部分業務快取session id作為異常的時候的備用,但這個不是很建議,原因很簡單,可能導致入口 不唯一,甚至造成安全漏洞,這裡需要具體案例具體分析)。有些路徑是可以設計為非關鍵路徑的,如資料上報,

 . 關鍵路徑的多級灰度模式。如果知道某個服務是關鍵路徑,比如在支付前的請求billno_server獲取唯一的訂單號,從業務流程看,這個肯定是一個關鍵路徑,沒有訂單號就無法下單,業務流程執行不下去,但如果每次下單都呼叫一次billno_server生成 一個訂單號,偶爾的網路超時或者失敗都是可能的,而對使用者來說,就是此次下單提示大家都非常熟悉得不能熟悉的一句話:“系統繁忙,請稍後再試”,那麼是否能夠做得更好呢?或者至少減少這種概率呢? 一種思路是每次請求一批billno快取到本地程序空間,然後使用的時候先從本地快取中取,沒有了再去請求;一種是請求失敗的時候,是否可以考慮用本地隨機生成一個,在極端情況下弱化對該關鍵路徑的依賴?  . 若關鍵路徑的資料唯一來源是本業務,則可以考慮自建部分熱點資料,一點出現問題,則切換到自建的部分熱點資料,繼續提供服務。

   6,考慮到手機客戶端的計算能力比較弱,在設計上是否把計算成本更多的往服務端移動,利用強大的伺服器端計算能力提升使用者體驗,這一點也是微信架構設計給筆者的一個感受。
   
 三,優化連結
     如何管理連結是一個老生常談的話題了,這裡主要長連線和短連線的問題。當然還有一些什麼連線池等策略。 
     弱網路環境下,建立連結的時間非常長,網路質量測試資料顯示,建立連結佔用耗時接近1/3,走短連結又導致連結頻繁,所以考慮將短連結改成長連結,在碎片時間內重複利用,減少建鏈耗時,此外,還有以下幾個優點: 

     1,C/S的持續連結使得後端能夠主動push關鍵資料到客戶端,例如實時的通知,新數字提醒等等,能很好的改善體驗,在短連結的情況下,只能依靠客戶端進行定時輪詢,不可避免的使新資料有所延遲。

     2,進一步節省短連結過程中的包大小,短連結情況下,每次來回請求,都不可避免需要帶上一些公共資料。長連結只用在建連結成功後的第一個包中上行這些資料,後續包則可以省掉這些欄位,進一步減少流量; 

     3,長連結還能有效的減少流量限制類手機軟體導致服務不可用的問題,有些流量限制類軟體會接管使用者的所有網路請求,以達到流量計算和斷流的目的,這種本質上就是一種劫持,使用長連結+私有加密協議, 可以使得對方無法準確分析包情況,減少劫持到來的服務不可用情況。

     4,長連結還可以減少在高併發下對臨時埠的依賴,有些使用短連結的服務,在高併發下,發現臨時埠不可用的問題也可以通過長連結得到緩急。 
 
     注意:使用長連結的時候,必然有長連結過期不可用的情況,因此,業務實現需要埋入重連機制。
 
 四,基於網路質量的多級服務設計
     手機的網路環境比較多樣,如wifi, 3G, 4G 還有2G等,不同的網路環境的體驗是不同的,對非常好的網路環境我們就不說了,關鍵討論一下在2G等比較惡劣的情況下的一些思考。

1,不同的網路環境是否具備多級的服務能力?如針對2g網路的使用者,顯示的內容更少? 圖片變成文字?一些功能入口不可用?

2,減少網路協議包的大小。在網速很慢的情況下,包的大小至關重要,直接影響成功率,可以考慮更加緊湊的協議(包括不必要的欄位不傳送)+壓縮演算法。這裡有個tips,大家知道cookie的內容都是每次跟在http請求一起傳送給到伺服器的, 對圖片,js,ccs等建議部署其他域名進行cookie隔離,這樣也可以減少一定的包大小。