淘寶開放平臺技術歷程

jopen 12年前發布 | 99K 次閱讀 淘寶 軟件架構

   2006年底,阿里巴巴提出了“Work at Alibaba”的戰略,20來號人就被拉到湖畔花園馬云的公寓里面開始一個叫阿里軟件的公司創業。當時對于“Work at Alibaba”有個朦朦朧朧的感覺,就是要為中小企業提供一個工作平臺,但是工作平臺又需要是一個開放的平臺,因為賣家的需求是長尾的,當時火熱的 Salesforce給了阿里人一些啟示,那就是做一個支持二次開發的工作平臺,半開放式的來滿足各種賣家的長尾管理需求。此時,軟件市場上就開始培養起來最早的一批TP(淘寶開放合作伙伴),迄今為止很多非常成功的TP就是從那個時候開始進入淘寶賣家市場。

  但經過一年的平臺建設,發現開發者非常難利用平臺做二次開發,只有阿里軟件公司內部團隊構建了三個不同的CRM軟件。這時候淘寶來了一個業界的技術牛人:王文彬(花名:菲青),這位淘寶新晉的首席架構師找到阿里軟件的平臺架構團隊,談到了當時業界還非常新穎的一種技術平臺——開放平臺,由于阿里軟件已經在做類似的開放工作,希望能夠以合作的方式來試水開放平臺。當時雙方都是一種嘗試的態度,因此最后敲定,投入一個人,兩周時間,看是否能夠出原型,如果可以,那么就繼續做,如果出不了原型,那么就此結束。兩周時間,負責阿里軟件的架構師放翁,參看著美國雅虎的開放模式,吭哧吭哧的就搞出了開放平臺第一個雛形,沒想到就這樣開啟了5年的開放之路。后面會根據時間軸來說一下開放平臺的產品和技術的變革,每一年會發生很多事情,但是調出的一點一滴是當年最有感觸的。

  2007年:萌芽

  SOA盛行的年代,內部架構服務化成為開放的第一步,內部服務不做好隔離,開放就意味著風險不可控。支付寶今天的服務框架SOFA(類ESB),淘寶的HSF(OSGI),阿里軟件的 ASF(SCA)都是那個年代的產物,但服務化帶來的痛卻是一樣的,不論是OSGI或者SCA之類的服務框架,本身服務化規約設計都類似,但難題也都擺在每個架構師和開發者面前——服務單元Bundle的粒度控制,服務之間依賴管理,性能與規范的沖突,調試與隔離的平衡。這些都使得一線開發者和平臺框架實現者出現非常多的矛盾,而這個過程最后能活下來的框架,最后都是摒棄掉了很多企業級的設計思路,因為SOA架構從企業級產品演變而來,而服務化后的內部平臺要面對的開放平臺天生就是互聯網的產物。

  2008年:雛形

  這一年到年底,平臺開放淘寶服務30 個,每天調用量2000w,這一年的開放平臺的開發者面向的客戶主要是阿里巴巴上的中小企業和淘寶C店賣家。開放平臺建設初期要解決的就是三個問題:1. 服務路由(外部可以獲取內部信息);2. 服務接口標準化(統一方式的獲得各種標準化信息);3. 授權(外部合法的獲取內部信息)。服務路由其實就是寫一個高效的HttpAgent,服務接口標準化就是對象文本化(Json,xml)。今天在各大開放平臺廣為使用的OAuth協議,當前處于0.6版本,沒有任何實際的互聯網開放平臺使用,直到Google 2008年底慢慢對外推廣開放的時候,OAuth被封裝到Google的Open SDK中,才使得很多中小互聯網公司使用這種看似極其復雜的兩階段授權交互模式。淘寶初期采用的是自有協議,因為OAuth2以前的邏輯復雜且使用不方便,直到2011年才開始支持OAuth2,同時做了部分的安全增強。授權解決了開放最大的一個問題:用戶安全的對應用訪問其數據受信。用戶從此不用赤裸裸的將用戶名/密碼交給一個應用軟件,應用也可以在允許的范圍內(操作,數據,授權時長)充分利用用戶授權來玩轉創意。

  有了上面的三板斧(路由,數據規范,授權),開放平臺正式開門迎客了,沒有對外做任何的推廣,數據就蹭蹭蹭的走到了第一個1000w日均調用,此時兩個互聯網的新興技術開始在開放平臺中嘗試,Memcached和Hadoop。今天看來這兩個技術已經被大規模使用,2008年時卻是在吃螃蟹,2 臺虛擬機要抗1000w的路由,勢必要求對于路由和校驗信息能夠有足夠強的緩存,Memcached無疑是最好的選擇,但當時號稱分布式緩存的 Memcached其實是集中式緩存的一種,真正的分布式緩存都還在糾結于一致性和效率的問題(2, 3階段提交)。此時需要有一種方式能夠保證效率(可擴展)和穩定性,于是我們封裝了Memcached客戶端,提升當時BIO的Java客戶端的性能,同時引入了客戶端負載均衡和容災的設計,這種設計已經被應用在現在很多大型分布式系統里面。另一方面每天上千萬的訪問也讓技術和產品對訪問的行為有很強的分析需求,此時Hadoop在雅虎的充分利用引起了我們的重視(當時的雅虎技術創新一直都是業界的領頭人),通過僅有的兩臺機器和一堆技術文檔,摸索著我們搭建了公司內部的第一個Hadoop集群,而所寫的Hadoop入門實踐也成為當時Hadoop入門的基礎文檔,對于每天2000w的日志分析需求來說,Hadoop用的是游刃有余,但隨著業務的不斷發展,Hadoop離線分析所帶來的問題也凸顯出來,MR程序面對靈活多變的分析需求顯得不易維護且效率低下(數據反復讀取分析),于是我們也開始思考怎么來改進一下這個新玩意兒。

  2009年:產品化

  這一年到年底,平臺開放淘寶服務 100多個,每天調用量4000w,這一年是開放平臺的開發者面對的主要是淘寶C店賣家,賣家工具成為服務市場的主流。這一年是變化的一年,阿里軟件年中的分拆使得開放平臺的歸屬有些微妙,一種情況是留在阿里云,作為集團的基礎設施,另一種情況就是跟著主要的業務需求方淘寶走,最后我們還是說服了博士,結束了阿里軟件的老平臺,淘寶正式開始自己的開放之路。來到了淘寶,業務開放迅猛增長,從30個API猛增到了100個API,沒有對外做任何業務推廣,平臺調用量到了年底翻番。此時技術上的挑戰又聚焦到了性能上,一次API call的業務消耗平均在30~40ms,開放平臺當時的平臺處理消耗平均在10ms左右。我們做了數據打點和分析,發現最大的消耗在于互聯網數據接收,同時大量的圖片數據上行,更是加大了平臺處理時間,同時從訪問日志分析中可以看到很多無效的請求也占用了非常多的處理時間,這也意味著無效請求和有效請求一樣在消耗著有限的容器線程資源。于是我們開始嘗試自己封裝字節流解析模塊,按需解析上行數據,一來提升數據分析的性能(并行業務和數據增量分析操作),二來可以用最小代價處理異常請求(當發現不滿足業務規范,則立刻丟棄后續所有數據),這塊實現被叫做LazyParser,主要的實現重點就是最小化數據緩存來并行業務和數據解析操作,上線后效果不錯,整體處理平均處理時間從10ms降低到了4ms(包含了異常處理的優化和解析性能的提升)。

  另一方面,Hadoop的MR問題也日益突出,一大堆MR的class維護成本高,性能問題也隨之出現。此時我們開始嘗試抽象分析業務場景,想到的是是否能夠通過配置就可以完成各種統計分析需求。要用配置替代code,其實就看是否可以窮舉code所實現的各種統計需求。當回顧SQL的理念時,發現其實所有的統計在切割成為KV作為輸入輸出時,所涵蓋的需求無非是max, min, average, sum, count, distinct(這個是2012年實現的,用了bloomfilter和AtomicLong),再復雜一些無非就是上述幾個操作結果的數學表達式運算,因此KV輸入和KV輸出的離散統計配置需求已經抽象出來了,接著就是把統計完的一組組KV根據K來做Groupby,就生成了傳統意義上的報表。(K,v1,v2…)從此以后,每天的統計需求都通過配置來改變,再也沒有一大堆MR代碼,同時一次數據輸入就可以完成所有分析的處理,性能上得到了極大的提高。(后話,當后面有人推薦我們去看hive, pig的時候,我們發現原來路都是這么走過來的)

  雖然Hadoop每日分析抽象出模型配置解決了性能和易用性的問題,但是對于即時分析卻不太適合,當時出于監控的需求,希望能夠一個小時就可以對數據做一次增量的分析,用于監控服務整體的調用情況,保證對異常問題的即時排查。由于一天4000w的量還不算很大,因此當時就直接考慮采用MySQL 分庫分表的方式然后定時的去做SQL的查詢,結果發現效果不錯。當然這個過程又產生了一個小組件,要直到4000w的日志數據寫磁盤和DB雙份必然會帶來不少的IO消耗,同時這個系統并不是帳務系統,丟掉一點日志也沒關系,因此就采取了異步批量數據外寫的設計(多線程守護各自的一塊Buffer頁,定時外刷或者滿頁外刷),這樣在雙寫的情況下,單機的Load也沒有超過0.7。

   但快到年底的時候,發生了一件事情讓我們頭痛不已,同時也成為了開放平臺的一個“隱形炸彈”。一天晚上,突然發生平臺大規模拒絕服務的告警,半夜爬起來觀察了一下整個集群,發現業務處理時間從平均的30~40ms,上升到了1s,仔細觀察了一下,某一個業務的響應時間大幅攀升,從原來20ms的響應時間飆升到了1s以上,此時由于Http請求的同步性,導致前端服務路由網關的集群線程都釋放的非常慢,阻塞處理這個業務的請求,而其他正常的業務(淘寶開放平臺背后的服務是不同團隊維護,處理時間從1ms到200ms都有)也無法被訪問,因此才有了開始的全線告警的產生。當晚后面發現是這個業務團隊的一次發布中忽略了數據庫索引建立導致服務耗時增加,但這個問題開始時不時的來拜訪開放平臺,開放平臺穩定性受制于任何一個業務方,這是不可接受的~~~對于這個問題,起先考慮集群拆分,將重要業務和不重要業務拆分,考慮到實施成本(不同服務的利用率差異很大)和業務隔離是否徹底(重點業務也會相互影響),放棄了這個想法。當時又想到了軟負載切割,Haproxy和LVS,一個是七層的網絡軟負載切割,一個是四層的負載切割,由于涉及到業務,于是還是考慮走七層的軟負載切割,嘗試一臺Haproxy掛7臺虛擬機,然后運行期可動態調整配置在出現問題的時候可人工干預切割流量。就這樣,我們有了告警以后可以手動切割的半人工方式干預措施,起碼不在心驚肉跳時手足無措了。但我們依然晚上睡不踏實…(期間考慮過Web請求異步化,Servlet3的模式來規避同步Http 帶來的平臺阻塞,但當時唯一支持Servlet3的jetty和tomcat做壓力測試,效果都很不穩定)

  2010年:平臺化

  這一年到年底,平臺開放淘寶服務 300多個,每天調用量8億,這一年淘寶正式開始對外宣傳開放,淘寶開放年,贏在淘寶,很多今天年收上千萬的TP在這個時候成為了先鋒(10年以前的可以叫做先烈),產品層面上,這一年除了賣家工具的繼續發展,SNS熱潮的興起帶動了淘江湖的買家應用,游戲應用的淘金者蜂蛹而入,開放的服務也繼續保持 300%的增速,覆蓋面從賣家類延伸到了買家類,從簡單的API提供,到了淘寶網站支持深度集成應用到店鋪和社區。

  8個億的訪問量下再用MySQL做流式分析已經不靠譜了,分析時間要求也從一個小時提升到了20分鐘,此時經過快1年半的Hadoop使用和學習,再加上對分布式系統的了解,正式開始寫第一版的流式分析系統,MR的抽象依舊保留,而底層的數據計算分析改用其他方式,這個“其他方式”和 Hadoop的差異在于:1. 分析任務數據來源于遠端服務器日志(主要通過pull而非push)。2. 任務分配和調度采用被動分配(有點類似于volunteer computing的模式),mater 輕量的管理任務,slave加入即可要求執行任務,對任務執行的情況不監控,只簡單通過超時來重置任務狀態。3. 任務統一由Master來做最后的Reduce,Slave可以支持做Shuffle來減少數據傳輸量和Master的合并壓力,Master負責統一輸出結果到本地。總的來說就是數據來源變了,數據不通過磁盤文件來做節點計算交互(只在內存使用一次就丟掉了),簡化任務調度,簡化數據歸并。這樣第一版本的流式分析出來了,當然后面這些設計遇到的挑戰讓這個項目不斷在演進,演進的各種優化幾年后發現都在hadoop或者Hive之類的設計中有類似的做法。這個系統3臺虛擬機抗住了8億的日志即時分析,MySQL日志分析就此結束。

   這一年另一個重大改變就是更多人對開放的價值有所認同,淘寶從一個部門的開放走到了淘寶公司的開放,什么叫做部門開放?就是在10年以前大部分的API開放都是開放平臺這個團隊來做封裝維護,30個api還可以支撐,100個api已經讓一個專業的小團隊應接不暇(當然不得不承認,迄今為止淘寶最有全局業務知識的還屬這個團隊的成員),300多個api這種勢頭基本上就無法由一個團隊來作了,業務變更帶來的接口不穩定經常被投訴,因此我們啟動了服務輕量化的“長征項目”,逐漸通過工具和平臺將服務接入變成自動化的方式,將原來開放一個服務需要點對點,手把手花一周時間實施完成的過程,通過自動化服務發布平臺,一個人一天時間就可以發布一個服務,并且服務的文檔,多語言版本SDK都自動生成。這樣就具備了服務輕量化的基礎,然后將各個新開放的業務采用這種模式接入,而老業務逐漸的歸還給各個業務方去維護。這樣一來,服務的“穩定性”(業務方面)得到了非常大的提升,用戶對于服務的滿意度也得到了極大的提高。

  但這擔子放下了,那擔子又挑上了,在上面談到去年后臺應用不穩定導致平臺整體不穩定的問題在輕量化以后出現的頻率和次數更多了,因為發布和維護都落到了后臺部門,此時對于各個系統的把控就更弱了,這晚上睡覺不安穩,KPI中的穩定性指標基本就沒法定了。唯一能夠徹底解決問題的辦法就是http服務異步化+事件驅動+虛擬隔離線程池。那年年中的時候對Jetty7做了一次壓測,發現Continuations的效果已經可以上正式環境了,于是開始在Jetty7的基礎上做Http服務異步化+事件驅動的封裝,同時也實現了一個虛擬隔離線程池做配合。具體設計細節這里就不多說了,參看blog,簡單描述原理就是:1. 將前端容器線程和業務處理隔離(類似NIO和BIO的設計差異)。2. 業務處理如果依賴于外部系統則采用事件驅動的方式來減少線程等待,同時提高線程占用資源的利用率(這點上來說理想和現實還是有很多細節差異的,在實現的時候必須根據依賴系統消耗時間占總時間的比例看是否需要事件驅動,事件驅動帶來的切換消耗是比較大的)。3. 通過一個大的線程池虛擬設置不同業務可消耗的最大資源數,來充分的共享資源在異常情況下限制業務占用過多資源(任務處理開始排隊而非無度的占用資源)。這個組件上線以后,沒過幾天就發生了一個典型的案例,一個業務2點開始響應時間從10ms上升到了40ms,然后繼續上升到200ms,當時給這個業務模擬設置最大的線程資源數是20個,就發現那時候由于RT時間提升,線程資源釋放的慢,20個慢慢的被消耗到頂了,此時這個業務的隊列開始從0到100到 200到…(當然防止內存過多占用,會丟棄超過隊列長度的業務處理),而其他業務還是正常的使用著資源,平臺平穩,到了4點多,業務方收到告警修復以后,RT時間下降到了10ms,隊列中的請求數量開始減少,最后隊列清空,線程資源占用下降到正常水平。從此以后震子同學開心的和我說:開放平臺穩定性的 KPI可以隨便大膽的寫幾個9了。(技術敢做敢想,才能高枕無憂)

  2011年:市場化

  這一年到年底,平臺開放淘寶服務758個,每天調用量19億,這一年SNS熱潮消退,游戲逐漸淡出,賣家市場依舊生意火爆(很多TP的年收益讓人咂舌),營銷工具嶄露頭角成為開發者新寵,淘寶客成為了開放新寵(這一年返利網和團購一樣火,只是前者收錢,后者燒錢)。

  就在開放平臺開發者前景一片大好的時候,出現了一個讓開放轉變和收縮的導火索,一家做營銷工具的公司“團購寶”,每天凌晨都會通過接口同步客戶設置的一些優惠商品信息到淘寶網,結果那天凌晨,微博上突然很多人說某些店都是一塊錢的便宜貨,要知道這種事情在微博盛行的時代,傳播速度之快,影響之大,當即很多賣家商品都被1塊錢拍下。最后發現是線下的商品價格不知道怎么全被修改成1塊錢,然后凌晨一同步,就導致出現了上面的一幕。從那時候開始,開放平臺的KPI中增加了一個重中之重——安全,包括后面的很多技術產品都是圍繞安全展開。此時第一個被波及提升能力的系統就是流式分析集群,20分鐘一輪的數據分析要求壓縮到3分鐘,同時數據量已經從8億每天增長到了19億每天,花了2個月時間斷斷續續的優化集群結構設計和單機處理能力,里面經歷的內容有一天我翻Hadoop的優化過程時看到了相似的場景,具體就不在這里贅述,詳細內容依然去挖blog。簡單來說:1. 充分利用多核能力用計算換內存。2. 磁盤換內存,用并行設計來保證整體業務時間消耗不變甚至減少。3. Slave shuffle來減少Mater的合并壓力。4 .數據壓縮減少數據傳輸消耗和內存占用。…

  另一方面,由于2010年對于jetty7的充分理解和封裝,此時看到了又一個新技術的契機,2010年的時候去美國參加Javaone,當時看到有老外用Jetty7的特性來實現Comet功能,Comet原先主要用于CS結構的應用搬到互聯網上,因為不能用TCP的長連接,所以不得不用 Http的長連接來替代原來的模式,同時國外開放平臺也關注很多新型的API設計,其中就有推ter的Streaming api,這種通過http長連接方式推送消息到外部isv的模式引起了我們的注意。因此我們決定將Jetty7上的封裝近一步升級,支持Comet長連接方式,后端通過事件驅動的模式主動推送內部消息給外部,避免外部輪詢業務接口。這個設計的最重要點就是如何用最有效最少的線程來守護多個長連接,支持到后端事件驅動的數據下行,如果給每一個長連接支持一個數據推送守護線程,自然即時性最高,但代價就是眾多空置連接的守護線程消耗,預知細節挖blog。這種模式剛出來的時候,從上到下都是質疑聲,覺得太不符合常規做法了,常規做法就是pull,認為開發和無法接受,認為穩定性一定不靠譜。經過2011年的雙十一,當天幾個“嘗鮮”的開發者一臺PC就支持幾百萬的訂單高速處理,就讓很多人明白了,技術要敢想,代碼要敢寫,細節要敢專,沒什么不可能。也就從這以后,多樣化服務TQL, Schedule API, ATS從開放平臺的土壤上都長了出來,為更多的場景,更多的終端,提供了各種解決方案和創新實現。

  2012年:垂直化

  這一年到現在,平臺開放淘寶服務900多個,每天調用量25億,這一年淘寶客由于公司方向轉變熱潮消退,無線乘勢而起,新業務(機彩票,酒店,理財等),P4P,數據類服務都開始運營API,開放平臺開發者的客戶群體也從C店賣家增加到了B的品牌商,渠道商等。

  這是一個業務多變的一年,這也是淘寶內部對開放平臺認可的新階段。第一個階段是放任不管,開放平臺部門自己要開什么,封裝什么。第二階段是開放什么業務方負責支持開放,但開放后的結果概不了解,也無所謂了解。第三階段就是業務主動要開放,開放后開始運營服務,培養ISV市場,帶動業務的正向發展。

  這一年由于業務量的增長以及分析需求到用戶緯度,因此在2011年底啟動了流式分析集群重構升級的項目,將新的分析集群項目命名為 beatles,希望他能夠象甲殼蟲一樣,小蟲吃樹葉,再多都吃的下。2011年底到2012年初,用了近2個半月的時間做了一次完整的重構,將那么多年的補丁經驗和老代碼重新設計和實現,并且將Mater根據業務可垂直切分,最終解決Master歸并壓力的問題,當然期間的技術優化點也不少,因為我們的目標從3分鐘壓縮到了1分鐘,而我們的數據量翻番,統計緯度細化到了用戶緯度(意味著結果也會很大,不靠文件做中轉如何來實現需要更多的分拆和協同設計)。

   這一年起了兩個比較創新的項目:JS SDK和無線SDK(IOS,安卓),這兩個SDK的出現一定程度上由業務和安全兩方面決定。首先2011年年底啟動了社區電子商務化的項目,也就是現在所說的輕電商(XTao)項目,將更多的網站和淘寶銜接起來,此時網站間的融合就要求更輕便和簡易,最成功的案例就是非死book,于是年初的時候,拿這FB的JS SDK一陣看,就開始動手寫了,期間很高興拉了UED同學入伙,這才使得這個JS SDK變的更加靠譜,更加專業(前端這活誰都可以玩,但要玩好最終還是要對那一系列苦逼的瀏覽器兼容有所深入理解,現在想想自己當時還是有點無知者無謂的)。同時有了JS SDK,買家類的服務安全性有所保證,因為原先的REST調用在授權以后是無法知道是否是用戶發起的還是服務器發起的,而JS SDK一定程度上還要校驗Cookie的有效性,可以部分的保證用戶的在場知情。而下半年的無線SDK,就是間或的苦讀1個月的各種文檔,然后就開始動手玩了,由于對Java語言,動態語言,腳本語言都有比較多的使用,因此Objective-C上手并不是那么困難,同時沒有涉及到過多的MVC的內容,做 SDK基礎層的東西還是比較得心應手,就這樣iOS的無線SDK版本就出來了,此時在開放平臺的技術團隊內部正在執行一個叫做Hack project的活動,其中一個自主項目就是安卓的SDK,因此一個月后,安卓的SDK順利的誕生了。這兩個無線SDK所擔負的職責就是把控無線安全問題,不僅淘寶,業界其實很多公司都還沒理解無線開放的風險到底有多大,OAuth2基本就無法保證無線的用戶安全,因此如何在SDK和服務端融入更高級別的安全設計,成為了無線SDK誕生的第一個重要需求。

    另一方面,開放平臺安全體系的構建成為2012年的重點,從兩個角度去對安全做的全方位的控制:1. 用戶。用戶授權更細化了授權操作范圍(細粒度到了數據范疇),授權時長。所有信息可監控,歸檔,快速定位,我們內部叫做Top Ocean,簡單說來就是對所有的訪問日志做歸檔,歸檔的載體是塊狀文件,歸檔時對塊狀文件的所有紀錄按照需求建立索引,然后保留索引,上傳本地文件到遠端分布式文件系統備份。實時的監控服務調用和應用訪問,授權異動。2. 第三方應用。采用監控集群對所有ISV的服務器做安全掃描,對普通的Web安全漏洞做掃描,對應用的可用性和響應時間做監控。同時,正式啟動聚石塔項目,提供彈性計算和存儲能力及可靠的安全網絡環境給ISV,幫助ISV提供自身應用的安全性。

  至此為止,5年左右的技術歷程部分的展示在了大家的面前,這些只是5年中比較有代表性的一部分,同時技術的發展也只是開放平臺的一部分,前5年是技術變革帶動開放平臺發展,而接下去5年將會是業務變革和理解帶動開放平臺的階段,對業務的理解直接決定了開放平臺的價值所在,上面文章中輕描淡寫的講了5年內不同開放業務的興衰,其實這背后卻有更多耐人尋味的故事,而5年后的今天淘寶的格局:集市(C2C),天貓(B2C),一淘(電商搜索返利入口),無線,新業務,O2O(本地生活),團購平臺(聚劃算),這些平臺的價值是什么?如何找到自身定位?如何借助外力發展?如何面對流量入口的興起,傳統互聯網企業的電商化,電商平臺的競爭?這些才是開放平臺2012及下一個5年的精彩所在。

原文鏈接

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!