1. 程式人生 > >15年資深架構師詳解:一個大型互聯網公司的微服務轉型實踐

15年資深架構師詳解:一個大型互聯網公司的微服務轉型實踐

微服務 架構 單片服務

微服務是一個比較大的話題,基於我的過往經歷,本文將以 Netflix 為例,分享一個大型互聯網公司如何從一個 Monolithic 的 APP 成功轉型到微服務。文章主要涉及微服務的產生歷史,應用場景,與單片服務區別,微服務帶來的技術、企業組織結構等方面挑戰,以及如何合理地選擇單片服務構架和微服務構架等內容。

微服務的產生歷史

如下圖,是微服務在 Google 的搜索結果:

技術分享

自 2014 年以來,微服務開始被關註,搜索的人越來越多,並在 2016 年左右達到頂峰。從地域來看,很多國家都在關註,如印度,歐洲等等,並且很多公司在使用微服務構架。以下以 Netflix 為例來分享微服務的演變過程以及帶來的挑戰。

Netflix 的微服務演化

我 2012 年加入Netflix,從中了解到:

  • Netflix 從 2008 到 2009 年就開始在自有數據中心做單片的 Web 應用,那個時期是很龐大的 Java 包,無數的程序寫在其中,造成很多問題。

  • 2010 年開始把重量級的部分轉出。

  • 2013 到 2014 年,其他的模塊也陸續轉出,並發布很多 Open Source 的微服務工具,在矽谷及全球受到很多人的關註。

  • 直至 2015 年左右,Netflix 基本完成向微服務的轉型,也徹底從自有數據中心,轉移到亞馬遜的雲平臺。

如下,是微服務示意圖:

技術分享

微服務看上去很復雜,其實它是一個個服務器組成的,這些服務器之間相互連接。

如下圖,是 Netflix 在微服務方面的使用情況

技術分享

從時間點看,Netflix 是矽谷采用微服務比較早的公司,在采用過程中也受到很多質疑,特別是傳統公司,從數據中心遷到雲上,需要時間來慢慢接受。

微服務、單片服務兩者的概念與區別

如下,是很普遍的 Monolithic APP 示意圖:

技術分享

從 powser 到各種公司的 Apache,形成一個包含各種功能的 WAR 包,最後是一個 MySQL 的存儲層。這樣的方式,比較易於測試,部署方面也很簡單。

Monolithic APP 的優點如下

  • 易於開發。很多 IDE 和框架都支持,比如 Sprint MVC、Ruby Rails、Python Django 等。

  • 易於測試。可以通過簡單啟動應用程序並使用 Selenium 測試 UI 來實現端到端測試。

  • 易於部署。只需將打包的應用程序復制到服務器。

  • 易於擴展。通過在負載平衡器後運行多個副本,可以輕松地水平擴展。

  • DevOps 比較簡單。一支專門 DevOps 團隊負責即可。

Monolithic APP 的缺點如下:

  • 應用程序太大且復雜,很難完全理解並快速正確地進行更改。

  • 應用程序會越變越大,可能會減慢啟動時間。

  • 必須在每次更新時重新部署整個應用程序。

  • 如果代碼庫有新的變化,變化的影響通常不是很清楚,這導致廣泛的手動測試。

  • 連續部署很困難。

  • 當不同模塊具有沖突的資源需求時,單片應用也可能難以擴展。

  • 可靠性差。任何模塊中的錯誤(例如內存泄漏)都可能會導致整個網站宕機。此外,由於應用程序的所有實例是相同的,該錯誤將影響整個應用程序的可用性。

  • 采用新技術或框架很困難。由於框架或語言的變化將影響整個應用程序,因此在時間和成本上都是非常昂貴的。

隨著代碼庫,組件和團隊規模增長,各種問題相繼出現。

主要概括為如下幾點:

  • 原代碼太大,IDE 打不開了。

  • 單機的內存不夠,沒法編譯和跑代碼。

  • 部署一次要花很長時間。

  • 開發速度跟不上產品的需求,一個小小的變化需要整個源代碼重新編譯。

  • 某一個模塊裏的一個小錯誤,可能導致整個網站宕機。

隨著組織的成長,功能的增多以及技術棧的瓶頸出現,需要有新的變革。但面對如此龐大的視頻網站,有的程序都是用的 Java 包,自有數據中心,當時還沒有微服務的概念,但已經有了把內容拆分出來的意識。

什麽是微服務?

“微”是指團隊、代碼行數或 API 端口的數目等指標的大小?都不是,不同人對微服務有不同定義。

個人比較贊同這個描述:Loosely coupled service orientedarchitecture with bounded contexts。

關鍵是 LOOSELY COUPLED和BOUNDED TEXT,LOOSELY COUPLED 意味著每個服務可以獨立更新,BOUNDED TEXT 意味著一個服務只要做自己的事情,外界以API等接口。

也就是微服務要實現獨立部署,擁有獨立技術棧、界定上下文,明確的所有權等特點。

微服務與單片服務的對比

如下,是微服務與單片服務很形象的對比圖:

技術分享

單片服務是把所有的東西放在一個大盒子裏,這個大盒子裏什麽都有。微服務更像是車箱,每個箱子裏包含特定的功能模塊和物品,所有東西可以很靈活地拆分出來。

也就是說,在 Monolithic APP 中,所有的部件都在一個巨大的軟件包中。在微服務的構建下,有很多獨立存在的小服務,通過 API 接口連接成大的系統。

如下圖,是 Monolithic APP 的架構:

技術分享

Netflix 會支撐很多設備,最初是所有設備通過一個負載均衡器到一個碩大的、什麽都包含的程序中,最後會成為一個碩大的 Oracle 數據中心。這樣一來,會產生很大問題,大家都很反感。

如下圖,是微服務的架構:

技術分享

上圖可以看出每個服務都可拆分,自有數據源,不一定是 Oracle,可根據業務場景用不同的數據庫,完全由各個團隊自己決定。

綜上是從技術角度分析 Netflix 為什麽選擇微服務,從商業角度來看 Netflix 選擇微服務的原因如下。

有三點原因:

  • 可用性(Availability)。24 x 7 防止單點失敗(single point of failure)。在巨大的 CODEBASE 情況下,經常一個小小的錯誤比如代碼中多加了一個冒號就會導致整個程序編譯不了甚至引起整個網站宕機。對於大型互聯網公司而言,一定要避免單片服務導致的宕機。

  • 可拓展性。Netflix 當時流量占到美國三分之一,超過 9000W 的付費用戶且增長非常快。一旦某部件達到瓶頸時要有迅速可拓展的能力,一般就是添加新機器讓它運轉。但在傳統單片服務上,整個部分綁定在一起,擴展非常困難。

  • 速度。對互聯網公司,特別是 ToC 需要快速推出,速度很重要。速度在互聯網時代是致勝的關鍵。

  • 大型互聯網公司推行微服務,一旦需要新功能,可立即新開一個微服務,或在幾個有限的微服務中進行改動,不需要像原來基於巨大的數據庫來改動。

微服務帶來的技術挑戰

軟件構架從單片服務向微服務轉型過程中帶來了很大的技術挑戰。下面選取自認為比較關鍵的內容進行分享。

主要涉及以下幾方面的挑戰:

  • 服務發現(Service discovery)。傳統單片服務相對簡單,但微服務有幾百上千的服務器,對用戶來講,服務器的選擇是個問題。

  • 運維復雜度增加 – DevOps。

  • 分布式系統本質上帶來的復雜度。

  • 網絡延遲,容錯。

  • 服務接口版本控制,存在不匹配。

  • 測試(需要整個生態系統來測試)。

  • FAN OUT - >增加網絡流量。

面對這些方面的挑戰,分享一些關鍵技術,如 Service discovery、服務註冊、服務註冊模式、瓶頸/熱點、熔斷器和測試等。

Service discovery

對用戶而言,最難抉擇的是去哪個服務器上取數據,解決方案有客戶端發現和服務器端發現兩種。

如下圖,是客戶端發現

技術分享

客戶端發現,就是客戶端布設 Service Instance,存放所有地址、各種信息。客戶端接收到數據之後,可自行判斷去哪臺服務器上獲取信息。

如下圖,是服務端發現

技術分享

客戶端不需要寫很多程序,而是通過 Load Balancer 把信息轉到某個服務器。

服務註冊

服務註冊表是服務發現的關鍵部分,是一個包含服務實例的網絡位置的數據庫,需要高度可用且是最新的。

服務註冊一定不能宕機,一旦出現問題,恢復非常困難。服務註冊和發現部分,Netflix 采用的是自研 Eureka 組件。

服務註冊模式

服務註冊模式分為自註冊和第三方註冊兩種:

自註冊模式。這種方法的一個很好的例子是 NetflixOSS Eureka 客戶端。Eureka 客戶端處理服務實例註冊和註銷的所有方面。

Spring Cloud 項目實現了各種模式,包括服務發現,可以輕松地使用 Eureka 自動註冊服務實例,只需使用 @EnableEurekaClient 註釋註釋您的 Java 配置類。

服務註冊模式相對簡單,並且不需要任何其他系統組件。但它將服務實例耦合到服務註冊表。您必須在您的服務使用的每種編程語言和框架中實現註冊碼。

如下圖,是第三方註冊模式

技術分享

開源註冊器項目—經 Registrator,會自動註冊和註銷部署為 Docker 容器的服務實例,支持多個服務註冊表,包括 etcd 和 Consul。

NetflixOSS Prana 主要用於以非 JVM 語言編寫的服務,它是與服務實例並行運行的邊路應用程序。 Prana 使用 Netflix Eureka 註冊和註銷服務實例。

Registrator 的優點是服務與服務註冊表斷開連接,不需要為開發人員使用的每種編程語言和框架實現服務註冊邏輯。

相反,在專用服務內以集中方式處理服務實例註冊。缺點是除非它內置在部署環境中,它是另一個高可用性的系統組件,需要設置和管理。

如何處理 FAN OUT

如下圖所示,單片服務裏請求只有一個,而微服務裏很多時候客戶端必須通過不同的微服務器才能把數據全部收集起來,請求繁多。

技術分享

如下圖所示,解決的方法就是 Cache:

技術分享

盡量把已經擁有的數據 Cache 起來,當訪問時,優先於 Cache,沒有再選擇其他部分。

瓶頸/問題

如下圖,當遇到整個服務中某個變成瓶頸的情況,就會調用 X,X 要從用戶帳戶裏拿數據。X 調用 Y,Y 也要從用戶帳戶裏拿數據。

技術分享

這樣一來,用戶服務會變成一個大大的瓶頸,一旦宕機,最前端的APP一定拿不到數據。

處理方法如下圖所示

技術分享

Netflix 用的比較多的方法是針對一些共用的數據不進行反復調用,可采用 HTTP HEADER 傳遞數據。

如何提高可用性(Availability)?

微服務並不一定能保證可用性,甚至有時微服務做不好更容易宕機,所以一定要采用一些好的容錯機制。

所謂容錯,原則上說就是當錯誤發生,盡可能讓一臺服務器宕機。常見的解決方式有 Time out、Circuit peaker(熔斷器)和 Bulkheads (艙壁)-Reject new request 三種。

熔斷器在 Netflix 用的比較多,如下兩圖所示,為熔斷流程:

技術分享

技術分享

熔斷器主要應用在當一個服務去它的下遊服務拿數據時,不應該直接拿,要通過一個熔斷程序。

當下遊服務出現錯誤,或延時很長時間,熔斷器就停止再到下遊服務拿數據,直接返回。熔斷器也會不斷進行判斷,服務是否恢復,恢復之後才會繼續拿取數據。

這樣一來,問題就會在某個地方被阻擋,不會出現服務接連問題,導致微服務出現大規模崩潰的現象。

微服務測試

測試是比較頭疼的環節,特別是微服務架構端到端變得特別困難,主要原因是幾百個服務隸屬於不同的團隊。

個人比較推薦單元測試(Unit Test)、服務測試(Service Test)。而端對端測試(End to End Test)要盡量避免,可以通過一些監控工具來完成。

還有 Netflix 采用 ChaosMonkey 工具來對延遲和服務可靠性進行測試。這裏值得註意的是,每個微服務至少要有三個實時備份,以免宕機後無法恢復。

微服務帶來的企業組織結構挑戰

之所以分享微服務帶來的企業組織結構挑戰,是因為歸根結底還是人在做事。微服務是去中心化,讓每個服務有獨立權,這樣會導致組織結構發生很大的變化。

企業的組織構架往往會反映在技術構架中,微服務在企業內部是否能夠成功,很大程度上取決於企業的組織構架和技術構架是否能夠匹配。

以 Netflix 為例,分享在向微服務構架轉變的過程中對團隊和企業構架帶來的挑戰。

優化速度,而不是效率

Netflix 在考量以速度還是以效率為優化核心,最終選擇了速度。因為速度是贏得市場最重要的因素,速度意味著了解客戶需求,並以比競爭對手更快的速度給予他們想要的東西。在競爭對手準備跟進的時候,已經轉到下一組改進。

速度和效率是什麽關系呢?強調效率通常意味著試圖控制開發過程的整體流程,以消除重復的工作並避免錯誤的同時註意降低成本。

常見的結果是,註重節流,而不是開源。如果你說“我這樣做是因為它更有效率”,那麽這個意想不到的結果就是讓你慢下來。

這不是鼓勵浪費和重復開發,但是應該先優化速度,效率成為次要。提高效率不是一個企業的終極目標,提高效率要以業務增長更快為結果。

以結果為導向,減少不必要流程

盡量增加每個微服務團隊的自由度,如開發工具,開發流程等方面,然後以結果為導向。

Netflix 有三個框架,其中 Java 占主流,每個團隊可根據自身情況選擇技術構架,甚至數據庫也可選擇 MySQL 或者 NoSQL。

盡量減少流程,為什麽有流程呢?流程往往是對過去的事情的總結,如對一些錯誤,經驗總結,之後用這個進行流程控制。

但過多的流程會減慢對新生事物和突發情況的反映速度。還有要明確每個團隊的目標,減少互相依賴關系。

如下圖,是傳統公司的產品開發流程

技術分享

大多數軟件開發團隊呈孤島狀,他們之間沒有人員重疊。軟件開發項目的標準過程從與用戶體驗和開發組的產品經理召開會議開始,一塊討論新功能的想法。

在代碼中實現該思想之後,代碼被傳遞給質量保證(QA)和數據庫管理團隊,經常需要進行很多溝通。與系統、網絡和SAN管理員的溝通往往是通過內部的 TICKET 系統,導致整個過程非常緩慢。

有些公司試圖用初創公司的形式開發產品,但初創公司開發團隊並不一定是微服務開發團隊。公司雖會有很多個小的初創公司形式的小團隊,但是每個團隊內部結構還是和傳統公司的團隊結構一樣。

如下圖,是微服務產品研發團隊

技術分享

微服務產品研發團隊沒有不同的產品經理、UX 經理、開發經理等,在其孤島中向下管理。

每個產品功能(實現為微服務)都有一名經理,他負責監督一個團隊,從構思到部署來處理各個方面微服務的軟件開發。

平臺團隊提供產品團隊通過 API 訪問的基礎架構支持,在整個過程中,都采用 DeVop 形式發布和維護產品。

如何合理地選擇單片服務構架和微服務構架

並不是所有的場景都適合微服務,要根據實際情況,選擇微服務或單片服務:

微服務適用於巨大流量、系統有一定復雜性、需要快速開發出新的產品、用戶數量增長迅速以及絕大多數 TOC 的互聯網公司。

單片服務的應用場景一般是流量比較小、功能單一或非常簡單、不會快速叠代以及企業內部工具,POC 工具或網站。

技術分享

前樂視美國視頻平臺技術總監以及Netflix 視頻內容平臺技術負責人。有 15 年以上互聯網公司(LinkedIn、樂視、Netflix 以及 PayPal)技術開發、構架以及團隊管理的經驗。主要負責的領域是高並發後端服務構架、微服務構架、大數據平臺構架等,以及端對端的整個產品開發。感興趣的領域是視頻,支付,互聯網金融以及電商領域。

以上內容根據羅軼民老師在 WOTA2017 “微服務架構”專場的演講內容整理。

技術分享


本文出自 “雪夜雕零” 博客,請務必保留此出處http://wangxy.blog.51cto.com/12562290/1958590

15年資深架構師詳解:一個大型互聯網公司的微服務轉型實踐