本文根據(jù)白輝在2016ArchSummit全球架構(gòu)師(深圳)峰會(huì)上的演講整理而成。ArchSummit北京站即將在12月2日開幕,更多專題講師信息請(qǐng)到北京站官網(wǎng)查詢。
非常榮幸在這里跟大家一起來(lái)探討“海量服務(wù)架構(gòu)探索”相關(guān)專題的內(nèi)容。
我叫白輝,花名是七公。2014年之前主要在阿里B2B負(fù)責(zé)資金中心、評(píng)價(jià)、任務(wù)中心等系統(tǒng)。2015年加入蘑菇街,隨著蘑菇街的飛速成長(zhǎng),經(jīng)歷了網(wǎng)站技術(shù)架構(gòu)的大
變革。今天分享的內(nèi)容來(lái)自于去年我們做的事情,題目用了一個(gè)關(guān)鍵詞是“籬笆”,籬笆的英文是Barrier,是指2015年蘑菇街面臨的問(wèn)題和艱巨的困難。我們?cè)竭^(guò)了這些籬笆,取得了很好的成果。
引言

今天分享的內(nèi)容主要分為五部分。第一部分,概述電商系統(tǒng)發(fā)展中期面臨的一般性問(wèn)題。第二部分,如何解決面臨的問(wèn)題,主要的策略是做拆分、做服務(wù)化。第三、四部分,服務(wù)化之后業(yè)務(wù)的大增長(zhǎng)、網(wǎng)站流量飛速的增加、“雙11”大促等的挑戰(zhàn)很大,我們做了服務(wù)的專項(xiàng)系統(tǒng)優(yōu)化以及穩(wěn)定性治理。第五部分,進(jìn)行了總結(jié)和展望。
電商系統(tǒng)發(fā)展中期面臨的一般性問(wèn)題
我們先看第一部分的內(nèi)容。

我總結(jié)了一下,一般電商系統(tǒng)發(fā)展到中期都會(huì)面臨三個(gè)方面的問(wèn)題(如圖)。第一方面是業(yè)務(wù)問(wèn)題。比如,一開始做業(yè)務(wù)的時(shí)候可能很隨意,一是并不考慮業(yè)務(wù)模型、系統(tǒng)架構(gòu),二是業(yè)務(wù)之間的耦合比較嚴(yán)重,比如交易和資金業(yè)務(wù),有可能資金和外部第三方支付公司的交互狀態(tài)耦合在交易系統(tǒng)里,這些非常不利于業(yè)務(wù)發(fā)展。第二方面是系統(tǒng)問(wèn)題。2014年我們面臨單體應(yīng)用,400人開發(fā)一個(gè)大應(yīng)用,擴(kuò)展性很差,業(yè)務(wù)比較難做。第三方面是支撐問(wèn)題,比如關(guān)于環(huán)境、開發(fā)框架和質(zhì)量工具等。這些是電商系統(tǒng)發(fā)展到中期都會(huì)面臨的問(wèn)題,中期的概念是用戶過(guò)了千萬(wàn),PV過(guò)了1億。

我們來(lái)看一下蘑菇街2015年初面臨的問(wèn)題。蘑菇街2015年用戶過(guò)億,PV過(guò)10億,業(yè)務(wù)在超高速發(fā)展,每年保持3倍以上的增長(zhǎng)。電商促銷、交易、支付等業(yè)務(wù)形態(tài)都在快速膨脹,我們需要快速支持業(yè)務(wù)發(fā)展,而不是成為業(yè)務(wù)的瓶頸。那么就是要去做系統(tǒng)的拆分和服務(wù)化。
系統(tǒng)拆分與服務(wù)化過(guò)程
第二部分的內(nèi)容,是關(guān)于蘑菇街系統(tǒng)拆分與服務(wù)化的歷程。
按照如下幾條思路(見(jiàn)圖),我們進(jìn)行系統(tǒng)拆分以及服務(wù)化。最開始,大家在同一個(gè)應(yīng)用里開發(fā)一些業(yè)務(wù)功能,都是選擇速度最快的方式,所有的DB和業(yè)務(wù)代碼都是在一起的。首先我們將DB做垂直拆分。第二步是做業(yè)務(wù)系統(tǒng)垂直拆分,包括交易、資金等。第三步是在系統(tǒng)拆完了之后要考慮提供什么樣的API來(lái)滿足業(yè)務(wù)的需求?這里我們要做數(shù)據(jù)建模+業(yè)務(wù)建模,數(shù)據(jù)建模方面包括數(shù)據(jù)表的設(shè)計(jì)和擴(kuò)展支持,數(shù)據(jù)模型應(yīng)該非常穩(wěn)定;業(yè)務(wù)建模方面,使用標(biāo)準(zhǔn)和靈活的API,而且盡量不用修改代碼或者改少量代碼就能支持業(yè)務(wù)需求。第四步是需要將業(yè)務(wù)邏輯下沉到服務(wù),Web層專注于展示邏輯和編排,不要涉及過(guò)多業(yè)務(wù)的事情。然后用SOA中間件建設(shè)服務(wù)化系統(tǒng)。最后會(huì)做一些服務(wù)的治理。

來(lái)看一個(gè)API服務(wù)化的例子,在做服務(wù)化之前和做服務(wù)化之后,交易創(chuàng)建下單業(yè)務(wù)有什么不一樣。服務(wù)化之前我們面臨的問(wèn)題有:入口分散,如果要在底層做任何一個(gè)微小的改動(dòng),十幾個(gè)入口需要幾十個(gè)人配合修改,這是非常不合理的一種方式;多端維護(hù)多套接口,成本非常高;還有穩(wěn)定性的問(wèn)題,依賴非常復(fù)雜,維護(hù)很難。我剛到蘑菇街的時(shí)候,一次大促活動(dòng)就導(dǎo)致數(shù)據(jù)庫(kù)崩潰,暴露了系統(tǒng)架構(gòu)很大的問(wèn)題和總量上的瓶頸。按照上面提到幾條思路去做服務(wù)化,看看有了哪些改善?首先是API統(tǒng)一,多個(gè)端、多個(gè)業(yè)務(wù)都用統(tǒng)一的API提供;其次是依賴有效管理起來(lái),大事務(wù)拆分成多個(gè)本地小事務(wù);最后降低了鏈路風(fēng)險(xiǎn),邏輯更加清晰,穩(wěn)定性更好。

2015年3月我來(lái)到蘑菇街之后,先制訂了服務(wù)化的規(guī)范,探討了到底什么是標(biāo)準(zhǔn)的服務(wù)化。在做服務(wù)化的過(guò)程中,發(fā)現(xiàn)大家代碼風(fēng)格完全不一樣,所以制定編碼規(guī)范非常重要。2015年8月,我們完成了各個(gè)模塊的改造,包括用戶、商品、交易、訂單、促銷、退款等,然后有了服務(wù)化架構(gòu)1.0的體系。在此基礎(chǔ)之上,我們進(jìn)一步做了提升流量和穩(wěn)定性等更深度的建設(shè)。2015年9月,我們實(shí)施了分庫(kù)分表和鏈路性能提升優(yōu)化,2015年10月做了服務(wù)治理和服務(wù)保障。

接下來(lái),以服務(wù)架構(gòu)和服務(wù)體系建設(shè)為主線,講一下去年整個(gè)網(wǎng)站架構(gòu)升級(jí)的過(guò)程。

在服務(wù)化1.0體系完成之后,我們得到了一個(gè)簡(jiǎn)單的體系,包含下單服務(wù)、營(yíng)銷服務(wù)、店鋪服務(wù)、商品服務(wù)和用戶服務(wù),還有簡(jiǎn)單的RPC框架Tesla。當(dāng)時(shí),我們并沒(méi)有做很多性能優(yōu)化的事情,但是通過(guò)業(yè)務(wù)流程化簡(jiǎn)和邏輯優(yōu)化,每秒最大訂單數(shù)從400提升到1K,基礎(chǔ)服務(wù)也都搭建了起來(lái)。

有了1.0初步的服務(wù)化體系之后,更進(jìn)一步,我們一是要繼續(xù)深入網(wǎng)站如資金等的服務(wù)化,二是要做服務(wù)內(nèi)部的建設(shè),比如容量、性能,這也是接下來(lái)要講的內(nèi)容。
購(gòu)買鏈路的性能提升

這個(gè)鏈路(見(jiàn)圖)是比較典型的電商鏈路,有商品頁(yè)、下單、支付、營(yíng)銷和庫(kù)存等內(nèi)容。一開始每個(gè)點(diǎn)都有瓶頸,每個(gè)瓶頸都是一個(gè)籬笆,我們要正視它,然后翻越它。

我們先來(lái)看第一個(gè)籬笆墻:下單的瓶頸。
2015年“3.21”大促的時(shí)候,DB崩潰了,這個(gè)瓶頸很難突破。下一個(gè)訂單要插入很多條數(shù)據(jù)記錄到單DB的DB表。我們已經(jīng)用了最好的硬件,但是瓶頸依然存在,最主要的問(wèn)題就是DB單點(diǎn),需要去掉單點(diǎn),做成可水平擴(kuò)展的。流量上來(lái)了,到DB的行寫入數(shù)是2萬(wàn)/秒,對(duì)DB的壓力很大。寫應(yīng)該控制在一個(gè)合理的量,DB負(fù)載維持在較低水平,主從延時(shí)也才會(huì)在可控范圍內(nèi)。所以DB單點(diǎn)的問(wèn)題非常凸顯,這座大山必須邁過(guò)去,我們做了一個(gè)分庫(kù)分表組件TSharding來(lái)實(shí)施分庫(kù)分表。

將我們寫的分庫(kù)分表工具與業(yè)界方案對(duì)比,業(yè)界有淘寶TDDL Smart Client的方式,還有Google的Vitess等的Proxy方式,這兩種成熟方案研發(fā)和運(yùn)維的成本都太高,短期內(nèi)我們接受不了,所以借鑒了Mybatis Plugin的方式,但Mybatis Plugin不支持?jǐn)?shù)據(jù)源管理,也不支持事務(wù)。我大概花了一周時(shí)間寫了一個(gè)組件——自研分庫(kù)分表組件TSharding(https://github.com/baihui212/tsharding),然后快速做出方案,把這個(gè)組件應(yīng)用到交易的數(shù)據(jù)庫(kù),在服務(wù)層和DAO層,訂單容量擴(kuò)展到千億量級(jí),并且可以繼續(xù)水平擴(kuò)展。TSharding上線一年之后,我們將其開放出來(lái)。

第二個(gè)籬笆墻就是營(yíng)銷服務(wù)RT的問(wèn)題。促銷方式非常多,包括各種紅包、滿減、打折、優(yōu)惠券等。實(shí)際上促銷的接口邏輯非常復(fù)雜,在“雙11”備戰(zhàn)的時(shí)候,面對(duì)這個(gè)復(fù)雜的接口,每輪鏈路壓測(cè)促銷服務(wù)都會(huì)發(fā)現(xiàn)問(wèn)題,之后優(yōu)化再壓測(cè),又發(fā)現(xiàn)新的問(wèn)題。我們來(lái)一起看看遇到的各種問(wèn)題以及是如何解決的。首先是壓測(cè)出現(xiàn)接口嚴(yán)重不可用,這里可以看到DB查詢頻次高,響應(yīng)很慢,流量一上來(lái),這個(gè)接口就崩潰了。那怎么去排查原因和解決呢?
首先是SQL優(yōu)化,用工具識(shí)別慢SQL,即全鏈路跟蹤系統(tǒng)Lurker。

這張圖我簡(jiǎn)單介紹一下。遇到SQL執(zhí)行效率問(wèn)題的時(shí)候,就看是不是執(zhí)行到最高效的索引,掃表行數(shù)是不是很大,是不是有filesort。有ORDER BY的時(shí)候,如果要排序的數(shù)據(jù)量不大或者已經(jīng)有索引可以走到,在數(shù)據(jù)庫(kù)的內(nèi)存排序緩存區(qū)一次就可以排序完。如果一次不能排序完,那就先拿到1000個(gè)做排序,然后輸出到文件,然后再對(duì)下1000個(gè)做排序,最后再歸并起來(lái),這就是filesort的大致過(guò)程,效率比較低。所以盡量要走上索引,一般類的查詢降低到2毫秒左右可以返回。
其次是要讀取很多優(yōu)惠規(guī)則和很多優(yōu)惠券,數(shù)據(jù)量大的時(shí)候DB是很難扛的,這時(shí)候我們要做緩存和一些預(yù)處理。特別是查詢DB的效率不是很高的時(shí)候,盡量緩存可以緩存的數(shù)據(jù)、盡量緩存多一些數(shù)據(jù)。但如果做緩存,DB和緩存數(shù)據(jù)的一致性是一個(gè)問(wèn)題。在做數(shù)據(jù)查詢時(shí),首先要看本地緩存有沒(méi)有開啟,如果本地緩存沒(méi)有打開,就去查分布式緩存,如果分布式緩存中沒(méi)有就去查DB,然后從DB獲取數(shù)據(jù)過(guò)來(lái)。需要盡量保持DB、緩存數(shù)據(jù)的一致性,如果DB有變化,可以異步地做緩存數(shù)據(jù)失效處理,數(shù)據(jù)百毫秒內(nèi)就失效掉,減少不一致的問(wèn)題。
另外,如果讀到本地緩存,這個(gè)內(nèi)存訪問(wèn)比走網(wǎng)絡(luò)請(qǐng)求性能直接提升了一個(gè)量級(jí),但是帶來(lái)的弊端也很大,因?yàn)楸镜鼐彺鏇](méi)有辦法及時(shí)更新,平時(shí)也不能打開,因?yàn)闀?huì)帶來(lái)不一致問(wèn)題。但大促高峰期間我們會(huì)關(guān)閉關(guān)鍵業(yè)務(wù)數(shù)據(jù)變更入口,開啟本地緩存,把本地緩存設(shè)置成一分鐘失效,一分鐘之內(nèi)是可以緩存的,也能容忍短暫的數(shù)據(jù)不一致,所以這也是一個(gè)很好的做法。同樣的思路,我們也會(huì)把可能會(huì)用到的數(shù)據(jù)提前放到緩存里面,做預(yù)處理。在客戶端進(jìn)行數(shù)據(jù)預(yù)處理,要么直接取本地?cái)?shù)據(jù),或者在本地直接做計(jì)算,這樣更高效,避免了遠(yuǎn)程的RPC。大促期間我們就把活動(dòng)價(jià)格信息預(yù)先放到商品表中,這樣部分場(chǎng)景可以做本地計(jì)價(jià),有效解決了計(jì)價(jià)接口性能的問(wèn)題。
再就是讀容量問(wèn)題,雖然緩存可以緩解壓力,但是DB還是會(huì)有幾十K的讀壓力,單點(diǎn)去扛也是不現(xiàn)實(shí)的,所以要把讀寫分離,如果從庫(kù)過(guò)多也有延時(shí)的風(fēng)險(xiǎn),我們會(huì)把數(shù)據(jù)庫(kù)的并行復(fù)制打開。

我們來(lái)看一下數(shù)據(jù)。這是去年“雙11”的情況(如圖)。促銷服務(wù)的RT得到了有效控制,所以去年“雙11”平穩(wěn)度過(guò)。

接下來(lái)講一個(gè)更基礎(chǔ)、更全局的優(yōu)化,就是異步化。比如說(shuō)下單的流程,有很多業(yè)務(wù)是非實(shí)時(shí)性要求的,比如下單送優(yōu)惠券,如果在下單的時(shí)候同步做,時(shí)間非常長(zhǎng),風(fēng)險(xiǎn)也更大,其實(shí)業(yè)務(wù)上是非實(shí)時(shí)性或者準(zhǔn)實(shí)時(shí)性的要求,可以做異步化處理,這樣可以減少下單對(duì)機(jī)器數(shù)量的要求。另外是流量高峰期的一些熱點(diǎn)數(shù)據(jù)。大家可以想象一下,下單的時(shí)候,一萬(wàn)個(gè)人競(jìng)爭(zhēng)同一條庫(kù)存數(shù)據(jù),一萬(wàn)個(gè)節(jié)點(diǎn)鎖在這個(gè)請(qǐng)求上,這是多么恐怖的事情。所以我們會(huì)有異步隊(duì)列去削峰,先直接修改緩存中的庫(kù)存數(shù)目,改完之后能讀到最新的結(jié)果,但是不會(huì)直接競(jìng)爭(zhēng)DB,這是異步隊(duì)列削峰很重要的作用。還有,數(shù)據(jù)庫(kù)的競(jìng)爭(zhēng)非常厲害,我們需要把大事務(wù)做拆分,盡量讓本地事務(wù)足夠小,同時(shí)也要讓多個(gè)本地事務(wù)之間達(dá)到一致。
異步是最終達(dá)到一致的關(guān)鍵,異步的處理是非常復(fù)雜的。可以看一下這個(gè)場(chǎng)景(見(jiàn)圖),這是一個(gè)1-6步的處理過(guò)程,如果拆分成步驟1、2、3、4、end,然后到5,可以異步地做;6也一樣,并且5和6可以并行執(zhí)行。同時(shí),這個(gè)步驟走下來(lái)鏈路更短,保障也更容易;步驟5和6也可以單獨(dú)保障。所以異步化在蘑菇街被廣泛使用。

異步化之后面臨的困難也是很大的,會(huì)有分布式和一致性的問(wèn)題。交易創(chuàng)建過(guò)程中,訂單、券和庫(kù)存要把狀態(tài)做到絕對(duì)一致。但下單的時(shí)候如果先鎖券,鎖券成功了再去減庫(kù)存,如果減庫(kù)存失敗了就是很麻煩的事情,因?yàn)閮?yōu)化券服務(wù)在另外一個(gè)系統(tǒng)里,如果要同步調(diào)用做券的回滾,有可能這個(gè)回滾也會(huì)失敗,這個(gè)時(shí)候處理就會(huì)非常復(fù)雜。我們的做法是,調(diào)用服務(wù)超時(shí)或者失敗的時(shí)候,我們就認(rèn)為失敗了,就會(huì)異步發(fā)消息通知回滾。優(yōu)惠券服務(wù)和庫(kù)存服務(wù)被通知要做回滾時(shí),會(huì)根據(jù)自身的狀態(tài)來(lái)判斷是否要回滾,如果鎖券成功了券就回滾,減庫(kù)存也成功了庫(kù)存做回滾;如果庫(kù)存沒(méi)有減就不用回滾。所以我們是通過(guò)異步發(fā)消息的方式保持多個(gè)系統(tǒng)之間的一致性;如果不做異步就非常復(fù)雜,有的場(chǎng)景是前面所有的服務(wù)都調(diào)用成功,第N個(gè)服務(wù)調(diào)用失敗。另外的一致性保障策略包括Corgi MQ生產(chǎn)端發(fā)送失敗會(huì)自動(dòng)重試保證發(fā)成功,消費(fèi)端接收ACK機(jī)制保證最終的一致。另外,與分布式事務(wù)框架比起來(lái),異步化方案消除了二階段提交等分布式事務(wù)框架的侵入性影響,降低了開發(fā)的成本和門檻。

另一個(gè)場(chǎng)景是,服務(wù)調(diào)用上會(huì)有一些異步的處理。以購(gòu)物車業(yè)務(wù)為例,購(gòu)物車列表要調(diào)用10個(gè)Web服務(wù),每一個(gè)服務(wù)返回的時(shí)間都不一樣,比如第1個(gè)服務(wù)20毫秒返回,第10個(gè)服務(wù)40毫秒返回,串行執(zhí)行的效率很低。而電商類的大多數(shù)業(yè)務(wù)都是IO密集型的,而且數(shù)據(jù)量大時(shí)還要分批查詢。所以我們要做服務(wù)的異步調(diào)用。比如下圖中這個(gè)場(chǎng)景,步驟3處理完了之后callback馬上會(huì)處理,步驟4處理完了callback也會(huì)馬上處理,步驟3和4并不相互依賴,且處理可以同時(shí)進(jìn)行了,提高了業(yè)務(wù)邏輯執(zhí)行的并行度。目前我們是通過(guò)JDK7的Future和Callback實(shí)現(xiàn)的,在逐步往JDK8的Completable Future遷移。這是異步化在網(wǎng)站整體的應(yīng)用場(chǎng)景,異步化已經(jīng)深入到我們網(wǎng)站的各個(gè)環(huán)節(jié)。

剛才我們講了鏈路容量的提升、促銷RT的優(yōu)化,又做了異步化的一些處理。那么優(yōu)化之后怎么驗(yàn)證來(lái)優(yōu)化的效果呢?到底有沒(méi)有達(dá)到預(yù)期?我們有幾個(gè)壓測(cè)手段,如線下單機(jī)壓測(cè)識(shí)別應(yīng)用單機(jī)性能瓶頸,單鏈路壓測(cè)驗(yàn)證集群水位及各層核?系統(tǒng)容量配比,還有全鏈路壓測(cè)等。
這是去年“雙11”之前做的壓測(cè)(見(jiàn)圖),達(dá)到了5K容量的要求。今年對(duì)每個(gè)點(diǎn)進(jìn)一步深入優(yōu)化,2016年最大訂單提升到了10K,比之前提升了25倍。實(shí)際上這些優(yōu)化可以不斷深入,不僅可以不斷提高單機(jī)的性能和單機(jī)的QPS,還可以通過(guò)對(duì)服務(wù)整體上的優(yōu)化達(dá)到性能的極致,并且可以引入一些廉價(jià)的機(jī)器(如云主機(jī))來(lái)支撐更大的量。

我們?yōu)槭裁匆鲞@些優(yōu)化?業(yè)務(wù)的發(fā)展會(huì)對(duì)業(yè)務(wù)系統(tǒng)、服務(wù)框架提出很多很高的要求。因此,我們對(duì)Tesla做了這些改善(見(jiàn)圖),服務(wù)的配置推送要更快、更可靠地到達(dá)客戶端,所以有了新的配置中心Metabase,也有了Lurker全鏈路監(jiān)控,服務(wù)和服務(wù)框架的不斷發(fā)展推動(dòng)了網(wǎng)站其他基礎(chǔ)中間件產(chǎn)品的誕生和發(fā)展。2015年的下半年我們進(jìn)行了一系列中間件的自研和全站落地。

我們得到了服務(wù)架構(gòu)1.5的體系(見(jiàn)圖),首先是用戶服務(wù)在最底層,用戶服務(wù)1200K的QPS,庫(kù)存250K,商品服務(wù)400K,營(yíng)銷200K,等等。
接下來(lái)我們看一下這一階段,Tesla開始做服務(wù)管控,真正成為了一個(gè)服務(wù)框架。我們最開始做發(fā)布的時(shí)候,客戶端、服務(wù)端由于做的只是初級(jí)的RPC調(diào)用,如果服務(wù)端有變更,客戶端可能是幾秒甚至數(shù)十秒才能拉到新配置,導(dǎo)致經(jīng)常有客戶投訴。有了對(duì)服務(wù)變更推送更高的要求后,我們就有了Matabase配置中心,服務(wù)端如果有發(fā)布或者某一刻崩潰了,客戶端馬上可以感知到,這樣就完成了整個(gè)服務(wù)框架連接優(yōu)化的改進(jìn),真正變成服務(wù)管控、服務(wù)治理框架的開端。
購(gòu)買鏈路的穩(wěn)定性提升

有了上面講到的服務(wù)化改進(jìn)和性能提升之后,是不是大促的時(shí)候看一看監(jiān)控就行了?其實(shí)不是。大流量來(lái)的時(shí)候,萬(wàn)一導(dǎo)致整個(gè)網(wǎng)站崩潰了,一分鐘、兩分鐘的損失是非常大的,所以還要保證服務(wù)是穩(wěn)的和高可用的。只有系統(tǒng)和服務(wù)是穩(wěn)定的,才能更好地完成業(yè)務(wù)指標(biāo)和整體的經(jīng)營(yíng)目標(biāo)。
下面會(huì)講一下服務(wù)SLA保證的內(nèi)容。

首先SLA體現(xiàn)在對(duì)容量、性能、程度的約束,包括程度是多少的比例。那么要保證這個(gè)SLA約束和目標(biāo)達(dá)成,首先要把關(guān)鍵指標(biāo)監(jiān)控起來(lái);第二是依賴治理、邏輯優(yōu)化;第三是負(fù)載均衡、服務(wù)分組和限流;第四是降級(jí)預(yù)案、容災(zāi)、壓測(cè)、在線演練等。這是我們服務(wù)的關(guān)鍵指標(biāo)的監(jiān)控圖(見(jiàn)上圖)。支付回調(diào)服務(wù)要滿足8K QPS,99%的RT在30ms內(nèi),但是圖中監(jiān)控說(shuō)明SLA未達(dá)到,RT程度指標(biāo)方面要優(yōu)化。
服務(wù)的SLA保證上,服務(wù)端超時(shí)和限流非常重要。如果沒(méi)有超時(shí),很容易引起雪崩。我們來(lái)講一個(gè)案例,有次商品服務(wù)響應(yīng)變慢,就導(dǎo)致上層的其他服務(wù)都慢,而且商品服務(wù)積壓了很多請(qǐng)求在線程池中,很多請(qǐng)求響應(yīng)過(guò)慢導(dǎo)致客戶端等待超時(shí),客戶端早就放棄調(diào)用結(jié)果結(jié)束掉了,但是在商品服務(wù)線程池線程做處理時(shí)拿到這個(gè)請(qǐng)求還會(huì)處理,客戶都跑了,再去處理,客戶也拿不到這個(gè)結(jié)果,最后還會(huì)造成上層服務(wù)請(qǐng)求的堵塞,堵塞原因緩解時(shí)產(chǎn)生洪流。

限流是服務(wù)穩(wěn)定的最后一道保障。一個(gè)是HTTP服務(wù)的限流,一個(gè)是RPC服務(wù)的限流。我們服務(wù)的處理線程是Tesla框架分配的,所以服務(wù)限流可以做到非常精確,可以控制在服務(wù)級(jí)別和服務(wù)方法級(jí)別,也可以針對(duì)來(lái)源做限流。
我們做了這樣一系列改造之后,服務(wù)框架變成了有完善的監(jiān)控、有負(fù)載均衡、有服務(wù)分組和限流等完整管控能力的服務(wù)治理框架。服務(wù)分組之后,如果通用的服務(wù)崩潰了,購(gòu)買鏈路的服務(wù)可以不受影響,這就做到了隔離。這樣的一整套服務(wù)體系(如圖)就構(gòu)成了我們的服務(wù)架構(gòu)2.0,最終網(wǎng)站的可用性做到了99.979%,這是今年6月份的統(tǒng)計(jì)數(shù)據(jù)。我們還會(huì)逐步把服務(wù)的穩(wěn)定性和服務(wù)質(zhì)量做到更好。

總結(jié)及下一步展望

最后總結(jié)一下,服務(wù)框架的體系完善是一個(gè)漫長(zhǎng)的發(fā)展過(guò)程,不需要一開始就很強(qiáng)、什么都有的服務(wù)框架,最早可能就是一個(gè)RPC框架。服務(wù)治理慢慢隨著業(yè)務(wù)量增長(zhǎng)也會(huì)發(fā)展起來(lái),服務(wù)治理是服務(wù)框架的重要組成部分。另外,Tesla是為蘑菇街業(yè)務(wù)體系量身打造的服務(wù)框架。可以說(shuō)服務(wù)框架是互聯(lián)網(wǎng)網(wǎng)站架構(gòu)的核心和持續(xù)發(fā)展的動(dòng)力。選擇開源還是自建,要看團(tuán)隊(duì)能力、看時(shí)機(jī)。我們要深度定制服務(wù)框架,所以選擇了自研,以后可能會(huì)開源出來(lái)。

服務(wù)框架是隨著業(yè)務(wù)發(fā)展不斷演變的,我們有1.0、1.5和2.0架構(gòu)的迭代。要前瞻性地謀劃和實(shí)施,要考慮未來(lái)三年、五年的容量。有一些系統(tǒng)瓶頸可能是要提前解決的,每一個(gè)場(chǎng)景不一樣,根據(jù)特定的場(chǎng)景選擇最合適的方案。容量和性能關(guān)鍵字是一切可擴(kuò)展、Cache、IO、異步化。目前我們正在做的是服務(wù)治理和SLA保障系統(tǒng)化,未來(lái)會(huì)做同城異地的雙活。
謝謝大家!
感謝陳興璐對(duì)本文的審校。