原文鏈接 http://www.litrin.net/2013/03/01/android%E4%B9%8B%E7%BD%91%E7%BB%9C%E4%B8%A2%E5%8C%85%E4%BA%8B%E4%BB%B6/
有那么一個應用,同樣的服務器端,同樣的Wi-Fi網絡下,Android連 接速度總是慢過iphone一個數量級。起先懷疑跟Android的硬件有關,無奈的是通過3G甚至於2G EDGE無線連接,速度均超過Wi-Fi。然后這個責任就一把歸結到了“Android不如iPhone”,“Android七拼八湊”之類無休止的平台 沙文主義之上了。
接手這個問題之后,起先也是渺無頭緒。先從服務器端的結構說起吧。
服務器端,很具有中國特色的電信、聯通、移動3入口結構,分別通過DNSpod指定到了3台Haproxy前端,通過這3台Haproxy主機發送 請求到3台Server,理所當然的3台Server公用一套數據層。通訊協議並非通用協議,為自身設計的一套基於XML的數據通訊協議,所有的通訊都是 TCP的持久連接。
起初的彎路也是被平台沙文主義帶到了一個誤區,我總是覺得Android手機的問題很可能是硬件驅動對於wi-Fi的支持不好。於是找來了一部手機,幾乎刷遍了所有能支持的通用Rom,無奈沒有任何起色。(話說Android刷機真的會上癮:mrgreen: )
然后就是懷疑Android的DNS跟iPhone的不同,無奈兩部手機的DNS均是統一DHCP獲得的。
回到網絡層上來,通過在路由器上監控Android的連接,終於發現Android會有經常性的連接丟包,發起連接很容易失敗。單由於是長連接的關系,一旦連接建立成功之后,后續的通許就會很暢通。
說實話,那個時候還是有偏見,認為可能是手機跟路由器的兼容有問題,於是更換了數個路由器,從802.11a一直測到802.11an!不加密 的,WEP的,PSK的等等試了個遍,依舊沒有進展。忽然發覺這種嘗試很可笑,於是自己在內網中寫了一個服務端模擬器,發覺沒有出現丟包,連接通暢。於是 在外網中試環境中,去掉了haproxy層,直連服務器,連接暢通!
問題已經大致上定位了,就是在Haproxy上!!難題才剛剛開始……
更換了多個版本的Haproxy,無效!
懷疑是Android的內核TCP設置有問題(比如滑動窗口,緩存之類的),由於Android本身就是一個Linux,直接Root之后(刷機積攢的經驗啊!)把/proc/sys/net路徑拷貝下來,一個個文件的對照,一個個配置的試了一天(觸摸屏打字很痛苦啊),幾乎已經按照服務器的要求配置了一台手機,毫無進展。
好吧,逼我動用終極手段了!數據截取!
刷回原版Rom,連接內網服務器模擬器,通過sniff對所有的通訊數據截包,區分iPhone和Android信包的不同。多次試驗之后,發現iPhone和Android每次的信包大小均不一致。Android信包總是大個12字節,終於找到問題了!
net.ipv4.tcp_timestamps
這個內核開關的含義是會在每個信包前增加一個符合RFC 1323標准的時間戳,正好12位。這個配置中,基於Linux內核的操作系統包括Android是默認開啟的,但BSD系統,包括iOS中類似的設置是關閉的。
把Rom刷回可root,直接修改內核這個配置,效果立竿見影!應該是解決問題了,但總不能告訴用戶“如果你們用Wi-Fi連接不了主機就直接去修改內核配置!”。
分析下來整個問題應該如此:
Haproxy可能存在 bug,或者我們配置有誤。Haproxy在轉發時可能會出現畸變的數據包,導致數據無法被送達到服務層。但這種狀況並不是每次都能被激發(我偏向解釋為 這是Haproxy的bug)。看了下Haproxy的文檔,他們只能解包Http,對於非Http的tcp協議,更多的只是轉發數據包而已。對於說為什 么手機網絡不會受這個影響,個人覺得Android並不是單純的一個給手機准備的操作系統,移動網絡配置並不是存在於內核之中的,電話也好,移動網絡也 好,是通過應用程序層實現的功能。
好吧,把Haproxy的主機全部設置為net.ipv4.tcp_timestamps=0,Android馬上跟iPhone享受了同等的待遇。
總結:
- Android是當前發行量最大的Linux版本。
- 糾結於“誰比誰強”之類的話題只會耽誤事,把結論歸結到類似的話題上更是無聊至極。只有用不好,沒有不好用!
- 數據截取之類的所謂黑客技術,有時可以更快的找出問題。

