【2016杭州·雲栖大會】阿裡百川在“淘寶移動技術實踐&開放”專場演講中,分别邀請了來自淘寶移動平台基礎平台部負責人吳志華(花名:天施)和阿裡百川負責人斯登宇(花名:承淵)等嘉賓分别做了精彩演講。以下是離青和冰撤的演講實錄:
陳以鎏(離青) 阿裡巴巴資深研發工程師:大家下午好,這個主題是雲時代下的性能優越和運維的實踐之路。首先做一個自我介紹,我花名是離青。
剛才為大家介紹了百川的整體的業務情況,提到“百川”時有兩個關鍵詞,商業和技術,技術是百川移動雲的部分,我們希望能夠承擔起為移動開發者賦能的偉大使命。
在基礎建構部分,我們有消息推送,多媒體和應用推廣,在運維支撐部分有應用回報。還有熱修複,同時移動安全、視訊服務、應用分析、輿情分析,我們在後續會有一系列的動作。
今天會圍繞應用監控和服務監控來展開。
那應用監控和服務監控構成了百川碼力apm,希望提供一站式的端到端應用監控,在應用監控部分能夠采集ios、安卓等資料,在服務這部分,從一些容器進行監控,同時支援到mysql和redis,最後是淘寶消息服務tmc、分布式開放架構dubbo,以及api,上到日志系統,之後我們的統計系統會進行計算和處理,來幫助開發者去長期對應用和服務做出智能前。同時進階的系統可以根據使用者設定的規則在問題發生時可以發出一些告警,幫助開發者及時解決一些問題。
接下來由我為大家介紹一下在百川碼力apm。
在應用開發時,程式錯誤、卡頓、資源越限,導緻系統朋友,這是我們面臨最嚴重的,也是我們首先要去解決的問題,在這裡,傳統領域手段,我們可以借助自動化的支援,可以發現一部分的應用問題,這些手段往往難以覆寫到使用者的真實的複雜場景,這一切都正常,但在崩潰的情況下會時有發生,如果希望去收集正式使用者的回報,我們往往會去使用裝置媒體或郵件回報的管道,後面的框是一個郵件标,如果我們使用這些管道能夠收集到一部分使用者回報,這些問題往往不能給到我們所需要的去解決問題所需要的這部分資訊,為了盡可能去收集使用者的真實使用場景中産生的這樣一些崩潰資訊,那碼力apm是引入了崩潰資訊暫行的工具,幫助開發者能夠解決應用中存在的問題。
在碼力apm控制台中會進行呈現,這裡呈現的是趨勢分析,我們将應用崩潰向一個次數彙內建時間曲線,希望能讓使用者去了解應用崩潰的整體趨勢。可以幫助開發者了解崩潰對于使用者産生的影響,而上方的這個可以在不同的本本和不同的時間裡做出崩潰趨勢的比對。
在崩潰的檢索裡面裡進行檢索管理,基于标簽和使用者的精确删除,在删除的結果當中,我們這邊會對統一調用進行聚合,我們會避免說崩潰鍊太長,這裡裝置數,是以幫你作出分析,标簽的部分可以對單條的崩潰作出簡單的歸類或管理這樣一些努力。點選單條,在崩潰長期頁面裡會成立崩潰統計方面的資訊,這裡給到崩潰的趨勢,基于裝置和趨勢的情況。
在下方是符号堆棧,我們還提供到了像是使用者、網絡、管道這樣一些資訊來幫助我們進一步去确定崩潰的這樣一個現場。那麼具體來說的話,我們是怎樣從用戶端上采集這些資訊的,蘋果的ios application crosh reports列舉出來了,進行信号捕獲的方式進行采集, resource可以通過cpu和記憶體檢測,exc guard可以通過中止檢測,hex value,可以通過卡頓、中止檢測來進行識别,這個議程主線程的卡頓來進行出發,其他是中止檢測來進行識别。
接下來我逐一為大家介紹一下所使用的檢測方式。
第一種方式信号捕獲,我們通過sigaction,可以通過程式運作時的狀态對于生成日志,還有衛星捕獲的方式,可以通過nssetuncaughtexceptionhandler,再根據崩潰日志的調用站統一調用崩潰,再到系統集中,與此同時,進階系統可以根據崩潰次數等資訊來發出及時的告警。那上報之後,這裡提供了檔案自動上報的流程,還可以提供上報腳本,在編譯時就可以上報到服務端。這裡第二次資料聚合,我們會将它進行聚合之後再到資料庫,這一次聚合過程可以減少dsym的檔案,與此同時,我們還提供了崩潰日志的解析的服務。這樣的話,我們可以更好地利用雲計算的能力去服務更多的開發者。
第二種檢測的方式是卡頓檢測。卡頓檢測的方式是依賴監控主線程的變更,在這裡我們視作為在操作上跑圈的“運動員”,我們會每隔一段時間的間隔去判斷是否跑過了一圈,如果在時間間隔之内沒有跑過一圈的話,說明在handle message(音)等過程當中消耗了過多的時間,這個時候就視為主線程發生卡頓。
與此同時,我們在這個地方會根據運作的不同時段,如運用到背景階段、控程的階段調整值。
第三部分是中止檢測,中止檢測不同于前兩種,通過檢測來發現問題的存在,那在中止檢測中具體是這樣做的,如果flag存在的話,就進行應用的非正常因素來上報。這裡有一個特殊的案例,就是我們的裝置有可能因為電量耗盡而非正常退出,這裡的話,我們會去檢測電池電量,電池電量很低的話,我們會清楚掉,這樣可以避免檢測的誤報。
第二塊,在應用開發過程當中,有請求錯誤、流量殺手、網絡劫持,這是需要我們去面臨另外一個棘手的問題,能夠發現簡單的網絡問題,這難以去識别到國内這麼複雜的網絡環境。與此同時,他們所采集的的網絡資訊,我們很難去幫他們導出進行一個長期的比對。如果使用手工的方式進入的話,一方面自己去面對各種各樣的系統的網絡接口,另一方面,我們應用的網絡代碼做變更時需要去對應更新我們的埋點代碼,去監控應用在真實網絡當中的性能。百川碼力推出了無痕埋點,我們希望開發者去長期監控自己的網絡性能,去優化自己的産品體驗。
那網絡的資料一樣的,上報了之後可以在百川碼力控制來做呈現,這裡我們可以給到一個總覽的資訊,可以給到平均響應時間,請求的次數和錯誤率的資訊。在右邊的拓撲的部分,以hos(音)作為區分,會顯示出每一個hos(音)的時間,點選展開了之後,會有這樣一個趨勢圖。
上方的部分是在不同的版本、不同的時段,不同的某個環境之間去做網絡性能方面的比對。
那進入到請求查詢頁面當中依然可以進入到篩選當中,時段、營運商和網絡環境去作出一個初步的資料篩選。我們優化了很大的url,那在這個選擇當中,我們還是可以通過hst(音)做出更精确的篩選。之後在右邊顯示出url單個的詳情,還有請求時間、次數和錯誤等資訊,包括趨勢圖,那點選這邊錯誤率的部分是可以進入到錯誤分析頁面,在錯誤分析頁面,我們會列出我們出錯次數最多的url,會有錯誤的分布。在上面的清單中,我可以根據url和錯誤位置進行篩選,可以根據發生的次數進行排序。那點選了之後可以進入到錯誤詳情頁面,錯誤的詳情頁面除了給到錯誤的分布之外,可以有使用者發生錯誤的日志,日志當中會有裝置資訊來幫助我們去定位使用者發生錯誤的這樣一個場景。
具體來說我們是怎樣實作網絡性能檢測的,ensuring ipv6 dns64/dat64 compatibitity給出的一個建議。
第一種是method swizzling,指向objc class,兩種會指向mbjc m為ethod,後面包括lel、char、imp(音),再通過mehtod、origin imp、imp,我們就可以在原始的行為前後再來替換進行實作。
第二種方式是proxy,包括nsproxy,和nsobject。
在我們的實踐中,我們是使用nsproxy,在收到一條消息時,如果這個消息不是我們的目标協定方面,也就是我們不實作這個方法的話,将它專發給delegate,這邊需要特殊注意的是,由于系統的多數的這種協定方法,多數是可選的,是以在這邊需要來額外聲明。
另外是fishhbook,我們以一個駕車的例子來說明。一個新手司機駕車從家裡開到一個目的地,老司機告訴他你怎樣走比較ok,之後的話,雖然第一次走會繞一點路,但之後再去的話,對應到程式運作的時候的話,我們程式運作時,我們的程式的目标調用的函數的話是dynamic,在初始的時候,dynamic不會包含到具體的時間、位址,是以在首次調用時,text stub helper,再通過dyld stub binder,之後調用再不用麻煩,就直接通過dynamic、la symbol ptr,如果要修改的話,有函數指向的話,我們就可以進行hook。這個事情需要大家看一下facebook相關的一篇文章。
下面inject cfnetwork,我們使用nsinpusttream,替換掉open和read:maxlength的方法,之後是stream:handleevent(音),再通過請求、響應、起止日期、錯誤、收發資料量,再到碼力,進行實時告警和資料存儲。讓使用者不需從零開始去進行開發,資料平台和控制平台就可以享受到可視化的根據,我們是歡迎大家去來使用産品的。接下來我們會冰撤同學來介紹一下服務的部分。
熊奇(冰撤)阿裡巴巴技術專家:剛才已經講了很多app端的管理相關的内容,我簡單自我介紹一下,我花名叫冰撤,目前是圍繞着如何降低開發者成本的工具。
今天所說的優化,對某一個應用程式進行一個活動,我們今天并不會說參數怎麼更加合理,今天将資訊優化和運維放在一起講,是因為這兩者從本質上來說是同樣一件事情,就是成本的關注是一個持續的工作,資訊優化是可以利用upm(音)的工具去持續地被關注、被改進的,到運維的體系裡,今天更多的是從産品來講講這件事情是怎麼去做更加全面、更加高效的。
之前我也請教了更多公司的運維大佬,其中有一位告訴我,這是一個非常有名的系列,他說對于使用者或者對于開放來講覺得很用,這是第一,總之不是太爽,這當然是一個玩笑。那怎樣做好?
服務端的性能管理這件事情總結下來是三點:可見、可靠、可控。無論是什麼樣的工具、什麼樣的系統,想要把這件事情做好的話基本跑不開這三點。我講一下。
如何可見?比如一個應用的通路情況,或是系統跟它産生關系的一系列的系統,或不同的系列決策,它們之間的互相關系做到可見,最典型的是現在流行的架構,這些架構帶來的複雜性更需要我們看清楚這些不同決策之間的互相關系,以上是從廣度上來說的。
深度上來說,系統裡的所有關鍵内容是要做到可見的,典型的是一個下單的流程,這個下單的流程過程當中是不是有一個接口錯了,或是某一個環節耗時?還有一個系統裡的各種異常也需要清晰、體系化地能夠展現出來。
可靠的是我們用的工具或系統是從這個角度而言的,資料采集是不是比較高效,分析資料的話,資料分析是不是足夠實,再一個是可靠性問題,關鍵時刻會不會掉鍊子。
可控是最根本的要素,隻有做到了可控才能說在宏觀上面采用一些效應,才能最大化地去控制成本。是以這個其實也是做運維的一個比較核心的事情,可控其實是典型的容量的可控,随着時間的推移,一個系統或一套系統,其容量變化是不是合理,是不是有趣,是不是比現在做得更好?比如一個叢集,典型的是一個業務系統,随着業務的發展,架構有沒有孵化,有沒有亂掉,有沒有引入一些不該有的依賴。還有系統裡的各種異動,無論大小都能夠第一時間感受到,這是可控上的典型的展現。
今天我們看來,很多同行對于應用型管理的要素有一個認知上的誤區,就覺得說這是做可視化的,我有很多功能,然後通過簡單地點一點滑鼠就能夠滿足很多工作。其實這個嚴格意義上來說,隻是第一步,就技術而言,無論角色是開發還是運維,我們做運維或者是做應用性管理,我們本質上而言我還是在于怎麼去控制成本,我們當然有很多開源工具或商業化工具,你仔細研究發現之後更多的是解決了可見或可視化的問題,在可靠和可控上還需要下很多功夫,這其實是需要一些長期的持續的投入和時間上的積累。
說到實踐,碼力apm在服務端的實踐,給大家看一下,如基礎資料怎麼看,基礎資料,第一是講全面,第二是講精細,比如app一部分的資料。該有的多有,這是全面。精細展現為,比如這裡這一張圖,這裡還分門别類的,比如是關鍵依賴的,精細再一個展現,我這一個系統所有的入口,無論是url,還是rtc接口,它的錯誤率是否也能夠分門别類地看到,這也是一個精細的展現。還有一點是上面沒有展現出來的就是基線,針對于曆史的營運情況,我現在的這些量,這些資料有沒有差很多,這個其實也是一個非常有價值的資料,這個也是在做容量可控的體系。
那基礎資料之外,我剛才其實說過,我們需要對應用和系統架構做一個持續的關注,去做架構上的可控。那往常的做法就是想做一些架構上的把控的話,最常見的是做人為梳理,在半年或一年的時候。現在系統已經怎麼變成這樣的,不行,要重構或改造這樣的,這樣的劇情大家應該非常熟悉。那我們認為對于架構的關注可以變成一個常态化的工作,就像這張圖所呈現的一個,它展現的三個事情,第一能夠實時地反映出來這個應用和應用的上下文關系,有了這個資料之後,架構師不用再去架構資料,通過驗證看出來下遊是哪些,就像這張圖展現的一樣,能夠看出來,比如有資料庫,有好一個dubble接口,還有http接口(音),再一個是能夠實時反映出來流量轉化上的東西,一個進來,然後繼續往下遊,進入某一個環節,到底是翻倍了,還是減慢了。還有一個是實時反映依賴的健康情況,就像這個圖一樣最左邊,我現在依賴的服務在報錯了,有了這個資料之後,可以幹的事情非常多。
落到細節層面,對于細節層面的關鍵鍊路都已經做了代碼級的工作,最典型的是一個請求是什麼,耗時,有哪些搜尋語句,包括具體的代碼層面的耗時,報錯,都能夠一眼就能夠看到。
再有一塊是異常,這個其實有很多同類型的産品或者是工具所忽視或沒有系統化去做的,當然,這個異常有很多出口,從什麼次元上去看什麼好,這是一個問題。通常的做法是看看這個系統有什麼用,或通路碼等,再結合日志進行分析,這是一種方式。我們采取的方式是依賴這個次元去切入的,為什麼要在這個次元上去做,通常來說,最容易出問題的,這往往是經常排查的,往往是出在應用依賴上的,應用出問題了,或依賴的資料庫出問題了。那我們對于應用的依賴做一個系統化的異常層面的關注,就相當于将異常的關注剛好卡在了一個層次上,就像這個圖所呈現的一樣,它呈現的是一個資料庫的依賴,包含了這個應用通路的資料庫的什麼時間發生了什麼錯誤,然後出現的次數、出現的錯誤有哪些,然後相應的這些錯誤的具體詳細是什麼樣的,等等,這些都有。基本上你有了這個層面的資料之後一個應用過去發生和正在發生的一切問題都一目了然了。
那有了這些資料之後還要解決感覺的問題,最重要的是通過告警,通過兩個,一個是你得足夠靈活,無論是剛才的基礎資料還是異常資料,都要能夠做到有足夠靈活的條件,通過不同的通道,然後讓相應的人感覺到,這第一。
第二點,對所有的這些告警都要做到可靠。你要能夠清楚地知道當時發生了什麼。就是這樣。
是以到這裡呢基本上我們在服務端的産品最關鍵的點,大家可以看一個具體的例子,這個例子的背景這樣的有一天一個天貓上的大賣家在天貓首頁上做一個活動,這個活動裡面引用了一個第三方的應用,通過這個第三方的應用将下單流程進行了定制,是這樣一個事情。活動沒多久,就收到了一條告警就說這個應用的響應時間特别高,第二部分,它去看看具體的應用場景到底怎麼樣,因為我們已經将它内部關鍵的服務的詳情都拎出來了,接着第三步是可以在應用整體層面看看調用到底在幹什麼事情。第一個是他發現在做圖檔上傳的事情,這個圖裡面的http(音)的目标位址都是多媒體服務的接口,然後他發現再一個是這些調用的kps(音)并不是很高。另外是兩種選擇,一種是看看服務,這個服務本身有什麼問題,再一個是它可以去看看手裡的其他資料,錯誤率基本為零,是以這些圖檔的接口,其實機率是比較小的,是以進一步去看看其他資料,如帶寬,它到了這裡會發現,所有的帶寬,對于天貓商業帶來的商量是沒有什麼概念的,是以說,它這個應用,從他收到短信到之後的解決,前後不過5分鐘的時間,它有這樣一個閉環的管理工具或運維工具,這是一個非常重要的事情。
這裡要稍微聽下來去講講原理性的東西,剛才所有的這些産品的實踐的功能,背後都需要有一些技術上的支撐,比如說資料采集相關的,甚至是資料呈現相關的,這些資料關系怎麼講一講資料采集方面的内容,因為這個是與應用直接打交道的部分。
剛才也說過代碼,還有一個潛台詞是無侵入,為何要無侵入?對于業務代碼,其中摻雜了很多,這對于一個做維護應用的同學來講肯定是不一樣看到的,背後是幫助使用者,對于一個最簡單的,我需要在前後将這些邏輯加上,将這些異常給加上等。
進一步看,舉一個java的例子,它其中可以輸出很多運作期的資料和功能,在這之上它提供了一個叫instrument的包,它提供給我們的一項能力是在加載的時候,具體到圖上而言,做修改的事情是通過一個transformer而實作的,可以将原始的碼拿過來交給transformer,transformer再對其進行改變。
這是基本原理。
經過轉換之後,這個還是最簡單的一種場景,真實的實作當中還是會解析一下目标調用的結果等,要做這些事情,這是一個基本的原理,相信它有比較高昂的代價,對于感興趣的元件都要去做改造,從web容器到架構等一系列的元件都要做相應的适配和相應的開發,所有的資料采集的實作都會不一樣,更不要說一些不同的容器或是架構也好,它都有不同版本的問題。是以說,總體來說,這樣一種方式的成本其實是不低的。
最後說一下使用者最為感興趣的是對性能的影響,畢竟已經嵌入到它的應用裡面去了,有三點,第一對流程的影響,第二是對于真實的資料鍊路的耗時影響有多少,總體而言,對于資料采集要有一個收集全異步,在什麼環節采集資料,采用異步化的方式,第二點,做了資料上的工作,對于采集下來的資料需要做一個品質上的控制,如過去15秒或30秒。再有一點,也是最重要的一點,是如何去保證對原程式的影響最小,因為剛才大家看過前後的比較的話,就會發現修改過後的碼,cpu會有更多的負擔,很多關鍵的資料要通過反射的方式來進行的,是以程度上而言的話,資料的擷取就已經落在了反射上,典型的方式有這一些,對于耗時影響不是特别敏感的,但又需要每次重新取數字的場景化,需要通過反射對象的内容。再一個,發生變化的場景,比如說一個資料庫或調用位址,對于這樣的一個場景可以将反射調用的結果緩存下來,要求更高一點的,要通過更麻煩的,加樁接口的方式,通過它來實作自定義的接口,這個接口隻有我自己,就可以将内部的一些資料直接透出來,在進行資料采集時直接通過自定義的接口來達到,這是一種方式。
這個就是關于資料采集方面的一些性能保證方面的内容。