日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

淘宝系App图片为什么在北京电信网络加载这么慢?

發布時間:2024/3/7 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 淘宝系App图片为什么在北京电信网络加载这么慢? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

歡迎訪問我的個人網站:https://coderyuan.com

文章目錄

  • 先講講怎么回事
  • 不能抓包
  • 初步判斷是DNS或IPv6問題(其實不是)
  • 反饋
  • 被逼無奈,只好搞逆向
    • 利用LayoutInspector找到ImageView
    • 探究一下TNodeImageView的源碼
    • 嘗試修改Smali——放棄
    • 編寫Xposed插件,抓取圖片URL
    • 利用Xposed進一步研究淘寶的圖片加載流程
      • 發現ImageLoader
      • 分析PhenixCreator
      • 捕獲圖片網絡流
      • 發現淘寶的網絡框架
    • 分析ANetwork網絡框架
      • 首先要把圖片的URL抓出來
      • 嘗試為ANetwork添加一個代理
      • 不能抓包,打一些日志總是可以的
    • 重點來了,分析ALog日志
    • 為什么北京電信慢?
  • 總結
  • 后記

先講講怎么回事

不知道怎么的,大概是從19年雙十一前,我在家里刷淘寶(天貓、閑魚等)的時候,圖片經常加載的特別慢,家里是北京電信的100M寬帶,另外還有一張電信的手機卡,無論寬帶還是4G,圖片都刷的很慢,網速正常,SpeedTest測試速度都是正常的,其他App也都OK

部分家里使用電信寬帶的同事也遇到了類似的問題,但都以為是家里網速的問題,所以也沒有向淘寶進行反饋,只是在需要的時候,切成4G使用罷了

今年5月寬帶到期,由于淘寶的問題,差點就換了聯通的,但由于聯通略貴(500M,166/月),電信(200M,600+/年),而且疫情期間,懶得折騰了,直接續費吧

于是就想著怎么解決一下淘寶圖片的問題

不能抓包

作為一名Android碼農,首先想到的辦法就是開Charles/Fiddler去抓包看看,但是在掛上代理以后,會發現抓不到大部分的淘寶圖片請求,于是猜測是淘寶使用了自己的網絡庫,或者是做了防抓包處理,所以看來不能直接通過抓包來判斷問題所在

后來在反編譯淘寶代碼的時候,也驗證了這一問題,其底層采用的并非OKHttp或者HttpURLConnection的方法去實現連接,而是使用了基于NDK實現的連接層(后面會講到)

初步判斷是DNS或IPv6問題(其實不是)

  • DNS:這種問題非常讓人首先懷疑DNS出了問題,畢竟這種大廠,都會根據當地網絡和服務器負載的實際情況,動態解析域名,選擇最優的CDN

  • IPv6:另外就是回想起19年雙十一前,貌似家里網絡對IPv6支持進行了升級,會不會是淘寶的CDN對IPv6兼容有問題

于是保證試試看的心態,改了一下路由器的DNS,嘗試過的DNS有:百度DNS(180.76.76.76)、阿里云DNS(223.5.5.5)、114(114.114.114.114)

然而發現并沒有什么卵用,還是一樣的慢……

想想也有道理,這種大廠App一般都會集成HttpDNS能力,隨你怎么改DNS,都不會影響人家的解析

然后就是關掉了IPv6功能,發現還是沒用,由于無意間通過Charles抓到幾張圖片的URL,ping了一下域名,發現其實淘寶的CDN還沒有支持IPv6……

所以圖片問題,和DNS、IPv6,根本沒有任何關系!!!

反饋

  • 首先是給淘寶客服反饋:

    不知道其他路徑能不能有效,反正淘寶App里面的反饋界面就跟擺設一樣,沒有任何作用!!

  • 反饋給在阿里工作的同學:

    問我要了一些信息以后,然后說給相關人員反饋一下,后來也沒有動靜了,據說很難推動去解決。。。

另外,我覺得,對于這種比較詭異的技術問題,還是得有一些有力的證據,可能才好推

被逼無奈,只好搞逆向

既然通過抓包、調試網絡環境,以及正規渠道都無法解決問題,那我只好自己排查了

于是準備好這些工具,準備開干:apktooldex2jarVSCodeAndroid StudioXposed,另外就是需要一臺ROOT后的Android手機,最好是Nexus或者Pixel

當然,也可以考慮使用VirtualXposed(https://github.com/android-hacker/VirtualXposed),這個工具的優點是不需要ROOT就可以使用Xposed的功能,且每次更新Hook不需要重啟手機,但是部分場景不太穩定,個人還是喜歡用ROOT以后的手機去裝原版的Xposed,不過需要Android 8.1及以下的系統

上述工具的使用,我就不再多說了,直接尋找突破口

利用LayoutInspector找到ImageView

在一臺ROOT后的手機上,是可以利用LayoutInspector抓取任何一個App的View的

因為經常刷微淘,而且圖片也比較多,加載比較慢,這里以淘寶的微淘模塊為例,看看它用的類名是什么

感謝淘寶沒有做更深入的類名混淆,微信的部分場景,混淆就做的非常狠,幾乎沒法看了

于是可以發現這個用于圖片顯示的類就是TNodeImageView

探究一下TNodeImageView的源碼

既然已經定位圖片控件,那么可以直接搜Smali文件或者使用Android Studio,在加載使用dex2jar轉換而來的Jar包以后,雙擊Shift搜索(和平時使用Android Studio搜索項目中的類一樣)

個人建議首先使用Android Studio或IDEA看Jar包里的源碼,如果發現不能被反編譯,或者某些App做了防dex2jar轉換,再考慮去看Smali,效率高的多,不太推薦用JD-GUI,不如IDEA系列IDE方便

使用VSCode直接搜索Smali文件:

如果使用Android Studio/IDEA,需要把jar包先引入到工程當中:

這里可以發現兩個方法:

  • 第一個是setImageUrl:

    很明顯是一個外部調用,用來設置圖片URL的方法,斷定這里可以獲取到圖片的URL

  • 第二個是onImageLoaded:

    其參數為一個BitmapDrawable對象,猜測是圖片加載框架的回調方法,用來設置解碼后的圖片

嘗試修改Smali——放棄

由于找到了圖片路徑的首個突破口,于是想著修改一下Smali,能夠讓淘寶直接打印圖片URL,然后直接把apk裝在手機上測試

經過apktool二次打包和jarsigner的一番折騰,apk是可以裝上了

但是發現,很多頁面出現白屏,登錄也無法使用,并且Logcat會打出一下Security相關的Log

這就說明淘寶做了簽名校驗,這個方法不可行……

編寫Xposed插件,抓取圖片URL

由于以上修改源碼的辦法行不通,那么只能考慮Hook的辦法,目前最流行的Hook技術無非就是Xposed了

關于Xposed,我就不再多說了,自行搜索即可,不過自我推薦一下自己寫的一個小工具,可以簡化Xposed Hook的開發,https://github.com/yuanguozheng/coderyuan-xposed-hook,如有需要,可以自行拿去使用

以下代碼即為利用coderyuan-xposed-hook實現對淘寶App「微淘」模塊圖片組件(TNodeImageView)的setImageUrl方法Hook

@XPHook(pkgName = "com.taobao.taobao",applicationName = "com.taobao.tao.TaobaoApplication",isUseMultiDex = true ) class TaobaoHookImpl {@HookMethod(className = "com.taobao.tao.flexbox.layoutmanager.view.TNodeImageView",methodName = "setImageUrl",isHookBefore = false,paramsCls = [String::class])fun hookTNodeImageView(param: XC_MethodHook.MethodHookParam?) {param?.args?.forEach {if (it != null && it is String) {log("TNodeUrl", it.toString())}}} }

跑起來以后,可以在Logcat中看到下面這些URL

于是我把這些圖片的URL抓出來,heic的圖片,去掉了.heic,即可獲取jpg或者png格式的數據,經過測試(PC瀏覽器、Android使用Glide等框架加載),結果發現如果我直接去訪問這些圖片,無論使用什么網絡,速度都是正常的

下圖是我的測試情況,網絡是中國電信4G,可以看到左上角的速度,也都基本保存3MB/s以上(圖片首次加載會比較慢。。。)

以上測試的App,使用如下代碼進行圖片加載

override fun onBindViewHolder(holder: ImgVH, position: Int) {Glide.with(this@MainActivity).load(jsonArray[position]).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE) // 強制不使用緩存.into(holder.imageView)}

這就說明如果使用較為常規的模式去加載淘寶上的圖片,其實是沒問題的,也進一步驗證了淘寶實際上是對網絡庫進行了修改,只是不知道具體做了什么事

利用Xposed進一步研究淘寶的圖片加載流程

發現ImageLoader

在TNodeImageView中,可以發現一個名為imageLoader,類型為p的類成員變量,猜測為淘寶自己的圖片加載框架

詳細查看p這個類,可以看到是一個abstract class

繼續查看p的實現類,可以發現一個名為j的類

于是研究j的源碼,再發現內部一段代碼,很明顯是用來加載圖片的功能,其內部的回調(onImageLoaded、onImageLoadFailed)、調用方式和命名,都和圖片有關,其中關鍵點就是PhenixCreator

分析PhenixCreator

根據PhenixCreator的包名,猜測這個框架的名字為:Phenix,暫且這么叫它

經過我對其反編譯后代碼的一番查看,可以發現以下兩個特點:

  • 其內部結構設計和接口調用方式,和Glide略微類似,畢竟大家都是ImageLoader,或多或少有一些共性

  • 看上去和Glide一樣,都可以比較方便的把網絡層組件換掉,同時會內置的類似HttpURLConnection的默認網絡層實現

其中,可以看到名為mImageRequest的變量,內部調用比較頻繁,而且其名字也基本能夠猜出作用,那就是做圖片請求

mImageRequest的類型為b(com.taobao.phenix.request.b)所以可以肯定b一定是用于在Phenix中管理圖片請求

然而此時,來回翻看b的源碼,難以發現有比較明顯的網絡請求痕跡,所以果斷嘗試另外一種思路,去尋找b的調用

這里我推薦使用Smali來搜索,但要注意相關的語法

可以發現名為com.taobao.phenix.loader.network.c的類使用了b,而且其包名包含network字樣,猜測是和網絡請求相關,果斷查看

從內部打出的Log,可以發現,這個類確實和網絡請求有一定關系,比如以下幾行代碼:

htr.a("Phenix", "received cancellation.", var1); htr.a("Phenix", "Network Read Started.", var9); htr.a("Phenix", "Network Connect Started.", var8);

其中不乏有很多Trace相關的操作,應該是進行統計打點相關的操作,用來收集性能相關信息的數據內容

捕獲圖片網絡流

仔細觀察代碼和Log,其中以下這段代碼吸引了我的注意:

看上去是對網絡請求的響應數據進行讀取,其中htv.a很有可能就是獲取網絡請求數據的方法,于是果斷點進去分析,這里再看到下面的代碼,很明顯是對一種InputStream進行操作,斷定是網絡流

那么htq.a這個方法又顯得格外耀眼,進去看了以后,htq類的內部結構如下,看樣子是一個對輸入流InputStream操作的工具類

public class htq {public static htv a(InputStream var0, a var1, int[] var2) throws Exception {...}public static void a(InputStream var0, a var1, huk var2) throws Exception {...// 內部包含很多對Stream的操作,以及OOM的檢測及異常拋出} }

很有可能第一a方法,其作用就是對圖片網絡流的讀取,這里沒有比較明顯的痕跡來判斷a方法的參數到底都是什么,所以只好借助Xposed來分析了

利用coderyuan-xposed-hook來Hook一下這個方法

@HookMethod(className = "tb.htq",methodName = "a",isHookBefore = false,paramsClsStr = ["java.io.InputStream", "com.taobao.tcommon.core.a", "tb.huk"])fun hookHTQ(param: XC_MethodHook.MethodHookParam?) {// 遍歷該方法的參數,由于是靜態方法,所以不要考慮首個參數是自己所在類的實例對象param?.args?.forEach {if (it != null) {log("YYY-htq", it.toString())}}}

運行起來以后查看Logcat,于是有了以下Log:

2020-05-25 21:10:40.284 29080-29908/com.taobao.taobao I/Xposed: YYY-htq: com.taobao.phenix.compat.mtop.b@ef09a67 2020-05-25 21:10:40.284 29080-29908/com.taobao.taobao I/Xposed: YYY-htq: tb.hth@96d165b 2020-05-25 21:10:40.284 29080-29908/com.taobao.taobao I/Xposed: YYY-htq: tb.huk@e275014

此時com.taobao.phenix.compat.mtop.b這個類映入眼簾,果斷查找,于是發現這個類確實為一個輸入流,且內部還包含一個ParcelableInputStream類型的看似是輸入流的變量a

b類內部實際是對ParcelableInputStream變量a操作的封裝,包含InputStream的常規操作,如:read、close

發現淘寶的網絡框架

由于找到了ParcelableInputStream,出于習慣地點進去看看,果斷發現新大陸,這個類位于一個非常醒目的類名下:anetwork.channel.aidl

于是對這個包名底下的類都查看一番

這還有啥說的!!!赤裸裸的網絡請求框架啊!

分析ANetwork網絡框架

首先要把圖片的URL抓出來

為了能夠驗證圖片請求確實走到這里了,第一步就是把ANetwork每次做請求的URL打印出來,看看有沒有圖片的URL

ANetwork的代碼混淆程度比較低,另外就是它還引用了anet.channel包中的很多內容,看樣子是一塊兒的,所以如果要比較全面地理解這個庫的流程,需要較為詳細的閱讀

我也是花了2-3天的時間去詳細地看了一把這個網絡庫的一些代碼,這里就沒有什么投機取巧的辦法,好好看看,基本能夠理解

經過研究以后,發現anet.channel.request.Request這個類是用來保存每次請求的基本信息的,內部還包含一個Builder類,所以可以Hook它的build()方法,然后把Builder內部的URL成員變量打印出來

@HookMethod(className = "anet.channel.request.Request\$Builder",methodName = "build",isHookBefore = true)fun hookRequest(param: XC_MethodHook.MethodHookParam?) {val instance = param?.thisObject ?: returnval oriUrlProp = instance::class.memberProperties.find { it.name == "originUrl" }oriUrlProp?.isAccessible = trueval formatUrlProp = instance::class.memberProperties.find { it.name == "formattedUrl" }formatUrlProp?.isAccessible = trueval ori = oriUrlProp?.getter?.call(instance)?.toString()val format = formatUrlProp?.getter?.call(instance)?.toString()val targetUrl = if (!format.isNullOrEmpty()) {format} else if (!ori.isNullOrEmpty()) {ori} else {null}if (targetUrl?.contains("heic.alicdn.com") == true) {log("YYY-Request-Url", targetUrl)}}

這里過濾了其他請求的URL,專門來看看圖片請求的URL,下面是Logcat的輸出:

2020-05-25 21:10:24.117 29080-29674/com.taobao.taobao I/Xposed: YYY-Request-Url: https://heic.alicdn.com/tps/TB1hPVmisKfxu4jSZPfXXb3dXXa.jpg_200x200q90.jpg_.heic 2020-05-25 21:10:26.589 29080-29909/com.taobao.taobao I/Xposed: YYY-Request-Url: https://heic.alicdn.com/tps/i2/O1CN011EAZ5L1gJ0OScCpUv_!!0-juitemmedia.jpg_200x200q90.jpg_.heic 2020-05-25 21:10:26.743 29080-29898/com.taobao.taobao I/Xposed: YYY-Request-Url: https://heic.alicdn.com/imgextra/i1/128/TB24Xy8l5OYBuNjSsD4XXbSkFXa_!!128-0-luban.jpg_200x200q90.jpg_.heic 2020-05-25 21:10:27.219 29080-29676/com.taobao.taobao I/Xposed: YYY-Request-Url: https://heic.alicdn.com/tps/i2/O1CN011EAZ5L1gJ0OScCpUv_!!0-juitemmedia.jpg_200x200q90.jpg_.heic 2020-05-25 21:10:27.370 29080-29908/com.taobao.taobao I/Xposed: YYY-Request-Url: https://heic.alicdn.com/imgextra/i4/170/O1CN01XXyKpn1D7tt9CAYT3_!!170-0-lubanu.jpg_200x200q90.jpg_.heic 2020-05-25 21:10:27.803 29080-29674/com.taobao.taobao I/Xposed: YYY-Request-Url: https://heic.alicdn.com/imgextra/i1/128/TB24Xy8l5OYBuNjSsD4XXbSkFXa_!!128-0-luban.jpg_200x200q90.jpg_.heic 2020-05-25 21:10:28.186 29080-29912/com.taobao.taobao I/Xposed: YYY-Request-Url: https://heic.alicdn.com/imgextra/i2/34/O1CN01bMPrqD1C7c4FGfAwy_!!34-0-lubanu.jpg_960x960q90.jpg_.heic 2020-05-25 21:10:28.388 29080-29674/com.taobao.taobao I/Xposed: YYY-Request-Url: https://heic.alicdn.com/imgextra/i4/170/O1CN01XXyKpn1D7tt9CAYT3_!!170-0-lubanu.jpg_200x200q90.jpg_.heic 2020-05-25 21:10:28.978 29080-29676/com.taobao.taobao I/Xposed: YYY-Request-Url: https://heic.alicdn.com/imgextra/i2/34/O1CN01bMPrqD1C7c4FGfAwy_!!34-0-lubanu.jpg_960x960q90.jpg_.heic 2020-05-25 21:10:39.375 29080-29898/com.taobao.taobao I/Xposed: YYY-Request-Url: https://heic.alicdn.com/imgextra/i2/164/O1CN015yuRLo1D59YXcfmvo_!!164-0-lubanu.jpg_960x960q90.jpg_.heic 2020-05-25 21:10:39.380 29080-29674/com.taobao.taobao I/Xposed: YYY-Request-Url: https://heic.alicdn.com/imgextra/i2/164/O1CN015yuRLo1D59YXcfmvo_!!164-0-lubanu.jpg_960x960q90.jpg_.heic

果不其然,圖片請求都是從這里構建的URL,也印證了上面的分析過程正確

嘗試為ANetwork添加一個代理

由于ANetwork的設計,導致無法直接使用Charles這種工具進行抓包,所以本想考慮使用Xposed,強制設置代理,但是經過一番嘗試,發現各類操作都沒有效果,這里就不詳細說了

而中途還發現其實這些請求并沒有走普通的HTTP連接,其連接過程是首先使用Spdy進行連接,而HTTP連接只是作為一種降級方案來兜底,那么就基本不能按照常規的方式去調試了

并且ANetwork的Spdy底層還是基于NDK實現(如上圖所示),并不像OKHttp這樣的網絡庫使用純Java來開發,所以看來,很難通過基本的逆向手段來添加代理,從而實現抓包了!

另外,還有一種可能就是:設置代理的地方,我還沒找到……

不能抓包,打一些日志總是可以的

在ANetwork的內部,有很多打Log的代碼,如下圖所示:

通讀ANetwork的代碼,發現ALog的調用確實很多,基本能夠確定ALog就是ANetwork專用的Log工具類,在很多關鍵位置,都使用了ALog輸出了相對詳細的日志信息,只是因為打正式包的時候,關掉了Logcat開關,所以無法在Logcat中打印出來

于是Hook ALog的所有靜態方法,讓ANetwork的日志,都能夠展現在Logcat當中

@HookMethod(className = "anet.channel.util.ALog",methodName = "e",paramsClsStr = ["java.lang.String", "java.lang.String", "java.lang.String", "java.lang.Throwable", "java.lang.Object[]"],isHookBefore = false)// 由于方法比較多,所以這里只列舉其中一個,即ALog.e的Hookfun hookLogcat2(param: XC_MethodHook.MethodHookParam?) {val logStr = getLogParamsStr(param?.args) ?: returnlog("YYY-ALog-E", logStr)}/*** 獲取Log參數,返回拼接后的字符串*/fun getLogParamsStr(objs: Array<Any>?, separator: String = "---"): String? {objs ?: return nullreturn StringBuilder().apply {objs.forEachIndexed { i, item ->if (item is String) {this.append(item)} else {try {this.append(gson.toJson(item))} catch (e: Exception) {}}if (i != objs.size - 1) {this.append(separator)}}}.toString()}

再次運行Hook,觀察ALog相關的日志,各類請求相關的信息一目了然

由于日志包含各類網絡請求的信息,在翻看日志的時候,發現有以下類似內容,并且在圖片加載不出來的時候,比較頻繁

YYY-ALog-E: awcn.SessionCenter---[Get]timeout exception---21646297---{"stackTrace":[],"suppressedExceptions":[]}---["url","https://img.alicdn.com/bao/uploaded/i1/TB1TXTMdKP2gK0jSZFoSuuuIVXa.jpg"]

于是過濾TB1TXTMdKP2gK0jSZFoSuuuIVXa字樣的Log,專門查看該圖片URL的相關信息,得到以下內容:

2020-05-26 10:28:40.376 29080-536/com.taobao.taobao I/Xposed: YYY-ALog-E: anet.UnifiedRequestTask---[traceId:Xr65l7NnDDkDAKlUmeifke5K15904601190960813129080]start---DGRD306---["bizId",null,"url","https://img.alicdn.com/bao/uploaded/i1/TB1TXTMdKP2gK0jSZFoSuuuIVXa.jpg"] 2020-05-26 10:28:40.378 29080-484/com.taobao.taobao I/Xposed: YYY-ALog-D: awcn.SessionCenter---getInternal---21646297---["u","https://img.alicdn.com/bao/uploaded/i1/TB1TXTMdKP2gK0jSZFoSuuuIVXa.jpg","sessionType","LongLink","timeout",0] 2020-05-26 10:28:40.385 29080-881/com.taobao.taobao I/Xposed: YYY-ALog-D: awcn.SessionCenter---getInternal---21646297---["u","https://img.alicdn.com/bao/uploaded/i1/TB1TXTMdKP2gK0jSZFoSuuuIVXa.jpg","sessionType","LongLink","timeout",3000] 2020-05-26 10:28:43.391 29080-881/com.taobao.taobao I/Xposed: YYY-ALog-E: awcn.SessionCenter---[Get]timeout exception---21646297---{"stackTrace":[],"suppressedExceptions":[]}---["url","https://img.alicdn.com/bao/uploaded/i1/TB1TXTMdKP2gK0jSZFoSuuuIVXa.jpg"] 2020-05-26 10:28:43.391 29080-881/com.taobao.taobao I/Xposed: YYY-ALog-D: awcn.SessionCenter---getInternal---21646297---["u","https://img.alicdn.com/bao/uploaded/i1/TB1TXTMdKP2gK0jSZFoSuuuIVXa.jpg","sessionType","ShortLink","timeout",0] 2020-05-26 10:28:44.377 29080-29994/com.taobao.taobao I/Xposed: YYY-ALog-E: anet.Repeater---[traceId:Xr65l7NnDDkDAKlUmeifke5K15904601190960813129080]end, [RequestStatistic]ret=1,statusCode=200,msg=SUCCESS,bizId=null,host=img.alicdn.com,ip=103.15.99.106,port=443,protocolType=https,retryTime=0,retryCostTime=0,processTime=3528,connWaitTime=3007,cacheTime=0,sendDataTime=191,firstDataTime=149,recDataTime=134,lastProcessTime=0,oneWayTime=4003,callbackTime=0,serverRT=0,sendSize=0,recDataSize=220008,originalDataSize=220008,extra={"firstIp":"103.15.99.106"},isReqSync=false,isReqMain=false,url=https://img.alicdn.com/bao/uploaded/i1/TB1TXTMdKP2gK0jSZFoSuuuIVXa.jpg---DGRD306---[] 2020-05-26 10:28:44.430 29080-475/com.taobao.taobao I/Xposed: YYY-ALog-E: analysis.FullTraceAnalysis---FullTraceStatistic|Xr65l7NnDDkDAKlUmeifke5K15904601190960813129080|https://img.alicdn.com/bao/uploaded/i1/TB1TXTMdKP2gK0jSZFoSuuuIVXa.jpg|img.alicdn.com|picture|null|wifi|https|0|1||1|0|0|0|0|1590412176629|1590411949467|1590412200433|3|com.taobao.tao.TBMainActivity|1590460108261|0||1590460119095|1590460119096|1590460120366|1590460120368|1590460123884|1590460123896|1590460124371|1590460124371|1590460124371|1590460124371|1590460124238|1590460124424|1590460124425|1590460124426|0|0|220008|220008|0|191|149|134|42|null|0|0|{}|200|---null---[]

重點來了,分析ALog日志

分析ALog的日志可以發現,其基本的請求過程是:

  • 建立一個UnifiedRequestTask任務,其內部是對一系列網絡請求、性能統計等操作的封裝

  • 接著交給SessionCenter建立或獲取可用的Spdy連接

  • 最后調用Repeater,生成TraceId,并進行數據上報

根據上面的Log,可以發現建立Spdy連接的過程,又分為以下幾個:

  • 首先會建立長連接,超時時間為0

  • 建立超時時間為3秒的長連接

  • 建立短連接

  • 然而出現這種情況的原因,看樣子是長連接無法建立,導致了TimeoutException,從而走了兜底邏輯,觸發建立了短連接,最終還是能把圖片顯示出來

    由于長連接的超時時間定義為3秒,所以在Repeater的數據中,如果發生了TimeoutException,那么connWaitTime基本保持在3000ms以上

    而正常的情況,大多數應該為0,或者1000ms之內

    所以一開始白圖,等一會兒能看到圖的時候,基本都在3s以后了,再加上一些排隊策略和解碼,10s以后都是有可能的……

    那么為什么不直接都走短鏈接?做過網絡性能優化的,這個問題肯定不難解釋

    最關鍵的原因還是為了加速

    眾所周知TCP連接的建立過程,需要經過3握手,短連接頻繁建立、斷開TCP連接,增加了很多額外的開銷,影響客戶端請求速度的同時,會額外增加服務器的壓力

    然而不建立固定連接的Quic,目前來說,并不成熟,使用長連接Spdy,對阿里這種公司來說,無非是目前最優的一種解決方案

    在ANetwork庫中,也可以看到Quic的相關實現,可以說淘寶在這方面還是緊跟時代潮流的,且幾種連接機制都可以比較靈活地切換,最終還有普通的HTTP作為兜底策略,可以兼顧性能和穩定

    為什么北京電信慢?

    在測試過程中,我使用了電信、聯通、移動的網絡,其中只有北京電信的寬帶、蜂窩能夠出現TimeoutException,其他家的網絡都是正常的,且connWaitTime值始終處于較低的水平

    所以推測出以下幾點原因:

  • 北京電信網絡對長連接支持較差,可能會導致無法連接的情況

  • 淘寶的圖片CDN服務(包括heic.alicdn.com,img.alicdn.com,gw.alicdn.com等域名),北京電信線路優化上可能出現了問題

  • 淘寶App內部的連接池可能需要改進,處理一些類似的極端Case

  • 總結

    通過這次對淘寶App的逆向,不但讓我對淘寶App加載圖片的過程有了一定了解和認識,也讓我學習了不少優秀的技術思想,這里列舉一些

    • InstantPatcher

      猜測為淘寶的熱修復方案,對Java采取所有方法插樁的方式,App內每個方法第一行代碼都時一個IpChange對象,用來做熱修復

    • 完善的統計機制

      圖片框架Phenix、網絡框架ANetwork,其內部都有完善、詳細的性能及業務錯誤等信息的統計方法,便于進行性能評估和錯誤信息追蹤

    • 統一任務調度管理器

      不知道猜的對不對,淘寶內部包含一個名為rxm的庫,猜測是類似RxJava的實現,用來實現異步任務、UI回調、優先級調度等功能,可以實現統一的調度管理

    • HEIC圖片

      目前淘寶的內部很多圖片都使用了HEIC格式,并且App內部還內置了NDK解碼庫,HEIC比WebP更省流,在省流方面,淘寶一直做的都比較先進,很久之前就應用了WebP,且CDN可以非常方便地支持各類格式轉碼、壓縮等

    • ARM64支持

      Google Play現在正在推進64位so支持,而很多App還停留在v7,甚至v5的級別,淘寶則是增加了ARMv8a的so支持,雖然so的體積幾乎大了一倍,但是在如今64位手機CPU已經普及的情況下,換來的性能和體驗提升,這么看來還是非常值得的

    最后,感謝淘寶沒有做過分的混淆和防Hook,可以讓我豐富視野、學習進步!

    后記

    目前,我已經聯系在淘寶工作的同學進行反饋,并把我抓到的日志發給了他們,據說他們內部的同學也可以復現類似的情況,也正在跟進處理中

    但是截止我寫這篇文章時,這個異常還是沒有完全得到解決,使用北京電信網絡刷淘寶時,白圖的情況時好時壞,部分CDN資源還是有超時現象,希望淘寶的同學們加把勁,早日解決這一問題,讓我們北京電信用戶能夠更愉快地剁手!哈哈哈

    總結

    以上是生活随笔為你收集整理的淘宝系App图片为什么在北京电信网络加载这么慢?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。