當前位置:
首頁 > 知識 > 網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

網易考拉(以下簡稱考拉)是網易旗下以跨境業務為主的綜合型電商,自2015年1月9日上線公測後,業務保持了高速增長,這背後離不開其技術團隊的支撐。微服務化是電商IT架構演化的必然趨勢,網易考拉的服務架構演進也經歷了從單體應用走向微服務化的整個過程。

以下整理自網易考拉陶楊在近期Apache Dubbo Meetup上的分享。


考拉架構的演進過程

考拉在2015年初上線的時候,線上只有七個工程,商品詳情頁、購物車下單頁等都耦合在中間這個online的工程裡面。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

在上線之初的時候,這種架構還是比較有優勢的,因為當時考拉的開發人員也不是很多,把所有的功能都耦合在一個進程裡面,利於集中開發、測試和上線,是一種比較高效和節省成本的方式。

但是隨著業務的不斷發展,包括需求的逐步增多,開發團隊的不斷擴容,這時候,單體架構的一些劣勢就逐漸的暴露出來了,例如開發效率低:功能之間的相互耦合,不同需求的不同分支也經常會修改同一塊代碼,導致合代碼的過程非常痛苦,而且經常會出問題。

再例如上線成本高:幾乎所有的發布需求都會涉及到這些應用的上線,同時不斷增長的業務需求,也會使得我們的代碼越來越臃腫,造成維護困難、可用性差,功能之間相互耦合,都耦合在一個進程裡面,導致一旦某一個業務需求涉及的代碼或者資源出現問題,那麼就會影響其他的業務。比如說我們曾經在online工程裡面,因為優惠券兌換熱點的問題,影響了核心的下單服務。

這個架構在考拉運行的4到5個月的時間裡,從開發到測試再到上線,大家都特別痛苦。所以我們就開始進行了服務化拆分的工作。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

這個是考拉現在的分散式服務架構。伴隨著服務化的拆分,我們的組織架構也進行了很多調整,出現了商品中心、用戶中心和訂單中心等等。拆分其實是由業務驅動的,通過業務來進行一些橫向拆分或者縱向拆分,同時,拆分也會面對一個拆分粒度的問題,比如怎麼才算一個服務,或者說服務拆的過細,是不是會導致我們管理成本過高,又或者說是否會帶來架構上的新問題。

考拉的拆分由粗到細是一個逐步演進的過程。隨著服務化的拆分,使得服務架構越來越複雜,隨之而來產生了各種各樣的公共技術,比如說服務治理、平台配置中心、分散式事務和分散式定時任務等等。


考拉的服務化實踐

微服務框架在服務化中起到了很重要的作用,是服務化改造的基石,經過嚴格的技術選型流程後,我們選用了Dubbo來作為考拉服務改造的一個重要支柱。Dubbo可以解決服務化過程中服務的定義、服務的註冊與發現、服務的調用和路由等問題,此外,Dubbo也具有一些服務治理的功能和服務監控的功能。下面我將介紹考拉基於Dubbo做的一些服務化實踐。

首先來說一下 熔斷。

在進行服務化拆分之後,應用中原有的本地調用就會變成遠程調用,這樣就引入了更多的複雜性。比如說服務A依賴於服務B,這個過程中可能會出現網路抖動、網路異常,或者說服務B變得不可用或者不好用時,也會影響到A的服務性能,甚至可能會使得服務A佔滿整個線程池,導致這個應用上其它的服務也受影響,從而引發更嚴重的雪崩效應。

因此,服務之間有這樣一種依賴關係之後,需要意識到服務的依賴其實是不穩定的。此時,需要通過採取一些服務治理的措施,例如熔斷、降級、限流、隔離和超時等,來保障應用不被外部的異常拖垮。Dubbo提供了降級的特性,比如可以通過mock參數來配置一些服務的失敗降級或者強制降級,但是Dubbo缺少自動熔斷的特性,所以我們在Dubbo上引入了Hystrix。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

消費者在進行服務調用的時候會經過熔斷器,當服務提供者出現異常的時候,比如暫時性的不可用,熔斷器就會打開,對消費端進行調用短路,此時,消費端就不會再發起遠程調用,而是直接走向降級邏輯。與此同時,消費端會持續的探測服務的可用性,一旦服務恢復,熔斷器就會關閉,重新恢復調用。在Dubbo的服務治理平台上,可以對Hystrix上運行的各種動態參數進行動態的配置,包括是否允許自動熔斷,是否要強制熔斷,熔斷的失敗率和時間窗口等等。

下面再說一下 限流。

當用戶的請求量,調用超過系統可承受的並發時系統QPS會降低、出現不可用甚至存在宕機的風險。這就需要一個機制來保護我們的系統,當預期並發超過系統可承受的範圍時,進行快速失敗、直接返回,以保護系統。

Dubbo提供了一些基礎的限流特性,例如可以通過信號量的配置來限制我們消費者的調用並發,或者限制提供者的執行並發。但是這些是遠遠不夠的,考拉自研了限流框架NFC,並基於Dubbo filter 的形式,實現了對Dubbo的支持,同時也支持對URL等其他資源的限流。通過配置中心動態獲取流控規則,對於資源的請求,比如Dubbo調用會經過流控客戶端,進行處理並判斷是否觸發限流,一旦請求超出定義的閾值,就會快速失敗。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

同時,這些限流的結果會上報到監控平台。上圖中的頁面就是考拉流控平台的一個監控頁面,我們在頁面上可以對每一個資源(URL、Dubbo介面)進行一個閾值的配置,並對限流進行准實時監控,包括流控比率、限流次數和當前的QPS等。限流框架除了實現基本的並發限流之外,也基於令牌桶和漏桶演算法實現了QPS限流,並基於Redis實現了集群級別的限流。這些措施保障系統在高流量的情況下不會被打垮。


考拉在監控服務方面的改造

在服務化的過程中,系統變得越來越複雜,服務數量變得越來越多,此時需要引入更多維度的監控功能,幫助快速的去定位並解決系統中的各類問題。監控主要分為這四個方面,日誌、Metrics、Trace和HealthCheck。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

在應用程序、操作系統運行的時候,都會產生各種各樣的日誌,通過日誌平台對這些日誌進行採集、分析和展示,並支持查詢和操作。Metrics反映的是系統運行的基本狀態,包括瞬時值或者聚合值,例如系統的CPU使用率、磁碟使用率,以及服務調用過程中的平均延時等。Trace是對服務調用鏈的一個監控,例如調用過程中的耗時分析、瓶頸分析、依賴分析和異常分析等。Healthcheck可以探測應用是否準備就緒,是否健康,或者是否還存活。

接下來,圍繞Dubbo來介紹一下考拉在監控方面的改造實踐。

第一個是服務監控。

Dubbo提供了服務監控功能,支持定期上報服務監控數據,通過代碼增強的方式,採集Dubbo調用數據,存儲到時序資料庫裡面,將Dubbo的調用監控功能接入到考拉自己的監控平台。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

上圖中的頁面是對Dubbo提供者的服務監控,包括對服務介面、源集群等不同維度的監控,除了全局的調用監控,還包括不同維度的監控,例如監控項里的調用次數。有時候我們更關心慢請求的情況,所以會將響應時間分為多個範圍,比如說從0到10毫秒,或是從10到50毫秒等,這樣就可以看到在各個範圍內請求的數量,從而更好地了解服務質量。

同時,也可以通過各種報警規則,對報警進行定義,當服務調用出現異常時,通過郵件、簡訊和電話的形式通知相關人員。監控平台也會對異常堆棧進行採集,例如說這次服務調用的異常的原因,是超時還是線程滿了的,可以在監控平台上直接看到。同時生成一些監控報表,幫助我們更好地了解服務的性能,推進開發去改進。

第二個是Trace。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

我們參考了Dapper,自研了Trace平台,並通過代碼增強的方式,實現了對Dubbo調用鏈路的採集。相關調用鏈參數如TarceID,SpanID 等是通過Dubbo的隱式傳參來傳遞的。Trace可以了解在服務調用鏈路中的一個耗時分析和瓶頸分析等。Trace平台上可以展示一次服務調用,經歷了哪些節點,最耗時的那個節點是在哪裡,從而可以有針對性的去進行性能優化。Trace還可以進行依賴分析,這些依賴是否合理,能否通過一些業務手段或者其它手段去減少一些不合理的依賴。

Trace對異常鏈路進行監控報警,及時的探測到系統異常並幫助我們快速的定位問題,同時和日誌平台做了打通,通過TraceId可以很快的獲取到關聯的異常日誌。

第三個是健康檢查。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

健康檢查也是監控中很重要的一個方面,以更優雅的方式上線應用實例。我們和自動部署平台結合,實現應用的健康檢查。服務啟動的時候可以通過Readiness介面判斷應用依賴的各種資源,包括資料庫、消息隊列等等是否已經準備就緒。只有健康檢查成功的時候才會觸發出註冊操作。同時Agent也會在程序運行的過程中定時的檢查服務的運行狀態。

同時,也通過這些介面實現更優雅的停機,僅依賴shutdownhook,在某些情況下不一定靠譜,比如會有shutdownhook執行先後順序的問題。應用發布的時候,首先調用offline介面,將註冊服務全部從註冊中心反註冊,這時不再有新的流量進來,等到一段時間後,再執行停機發布操作,可以實現更加優雅的停機。


考拉在服務測試方面的改造

下面來介紹一下考拉在服務測試方面的實踐。服務測試分為介面測試、單鏈路壓測、全鏈路壓測和異常測試四個維度。

介面測試

通過介面測試,可以來驗證對外提供的Dubbo服務是否正確,因此我們也有介面測試平台,幫助QA更好的進行介面測試,包括對介面的編輯(入參、出參),用例的編輯和測試場景的執行等。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

單鏈路壓測

單鏈路的壓測,主要面對單個功能的壓測,比如要上線一個重要功能或者比較重要的介面之前,必須通過性能測試的指標才可以上線。

全鏈路壓測

考拉作為電商平台,在大促前都會做全鏈路壓測,用以探測系統的性能瓶頸,和對系統容量的預估。例如,探測系統的各類服務的容量是否夠,需要擴容多少,以及限流的閾值要定多少合適,都可以通過全鏈路壓測來給出一些合理的值。

異常測試

對服務調用鏈路中的一些節點進行系統異常和服務異常的注入,也可以獲取他們的強度依賴關係。比如一個非常重要的介面,可以從Trace獲取的調用鏈路,然後對調用鏈的依賴的各個服務節點進行異常注入。通過介面的表現,系統就會判斷這個介面的強度依賴關係,以改善這些不合理的強依賴關係。


考拉在API網關方面的改造

隨著考拉服務化的發展,我們自研了API網關,API網關可以作為外部流量的統一介面,提供了包括路由轉發、流控和日誌監控等一些公共的功能。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

考拉的API網關是通過泛化調用的方式來調用後台Dubbo的服務的。Dubbo原生的泛化調用的性能比普通API調用要差一些,所以我們也對泛化調用性能做了一些優化,也就是去掉了泛化調用在返回結果時的一次對象轉換。最終壓測的結果泛化的性能甚至比正常的調用性能還要好些。


考拉在多語言方面的改造

考拉在業務發展的過程中產生了不少多語言的需求,例如,我們的前端團隊希望可以用Node應用調用Dubbo服務。對比了易用性,選用了開源的jsonrpc 方案,然後在後端的Dubbo服務上暴露了雙協議,包括Dubbo協議和json rpc協議。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

但在實施的過程中,也遇到了一些小問題,比如說,對於Dubbo消費者來說,不管是什麼樣的協議提供者,都是invoker。通過一個負載均衡策略,選取一個invoker進行調用,這個時候就會導致原來的Java客戶端選用一個jsonrpc協議的提供者。這樣如果他們的API版本不一致,就有可能導致序列化異常,出現調用失敗的情況。所以,我們對Dubbo的一些調用邏輯做了改造,例如在Java客戶端的消費者進行調用的時候,除非顯示的配置,否則默認只用Dubbo協議去調用。另外,考拉也為社區的jsonrpc擴展了隱式傳參的功能,因為可以用Dubbo隱式傳參的功能來傳遞一些全鏈路參數。


考拉在解決註冊中心性能瓶頸方面的實踐

註冊中心瓶頸可能是大部分電商企業都會遇到的問題,考拉也不例外。我們現在線上的Dubbo服務實例大概有4000多個,但是在ZooKeeper中註冊的節點有一百多萬個,包括服務註冊的URL和消費者訂閱的URL。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

Dubbo應用發布時的驚群效應、重複通知和消費者拉取帶來的瞬時流量一下就把ZooKeeper集群的網卡打滿,ZooKeeper還有另外一個問題,他的強一致性模型導致CPU的利用率不高。

就算擴容,也解決不了ZooKeeper寫性能的問題,ZooKeeper寫是不可擴展的,並且應用發布時有大量的請求排隊,從而使得介面性能急劇下降,表現出來的現象就是應用啟動十分緩慢。

因此,在今年年初的時候就我們決定把ZooKeeper註冊中心給替換掉,對比了現有的一些開源的註冊中心,包括Consul、Eruka、etcd等,覺得他們並不適合Dubbo這種單進程多服務的註冊模型,同時容量能否應對未來考拉的發展,也是一個問號。於是,我們決定自研註冊中心,目前正在註冊中心的遷移過程當中,採用的是雙註冊中心的遷移方案,即服務會同時註冊ZooKeeper註冊中心,還有新的註冊中心,這樣對原有的架構不會產生太大的影響。

考拉新的註冊中心改造方案和現在社區的差不多,比如說也做了一個註冊數據的拆分,往註冊中心註冊的數據只包含IP, Port 等關鍵數據,其它的數據都寫到了Redis裡面,註冊中心實現使用了去中心化的一個架構,包括使用最終一致性來換取我們介面性能的一個提升。後面如果接入Dubbo,會考慮使用Nacos而不是ZooKeeper作為註冊中心。


未來規劃

考拉最近也在進行第二機房的建設,通過兩個機房獨立部署相同的一套系統,以實現同城雙活。針對雙機房的場景,Dubbo會做一定的改造,例如同機房優先調用,類似於即將發布的Dubbo2.7.0中的路由特性。在Dubbo在服務註冊的時候,讀取系統環境變數的環境標或者機房標,再將這些機房標註冊到註冊中心,然後消費端會做一個優先順序路由,優先進行同機房的服務調用。

網易考拉的服務架構如何從單體應用走向微服務化?|技術頭條

容器化也是我們在規劃的一個方向。隨著服務化進程的演進,服務數也變得越來越多,通過容器化、DevOps可以提升測試、部署和運維效率。

Service Mesh在今年非常火,通過Service Mesh將服務框架的的能力比如註冊發,路由和負載均衡,服務治理等下沉到Sidecar,使用獨立進程的方式來運行。對於業務工程的一個解耦,幫助我們實現一個異構系統,對多語言支持,也可以解決中間件升級推動困難以及各種依賴的衝突,業務方也可以更好的關注於業務開發,這也會是未來探索的一個方向。

以上就是我們團隊在服務化進程中的一些實踐和思考,謝謝大家。


聲明:本文為公眾號阿里巴巴中間件投稿,版權歸其所有。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 CSDN 的精彩文章:

Google 的隱私噩夢來了……
你離優秀的開發者還有多遠?

TAG:CSDN |