基於容器的微服務架構剖析

基於容器的微服務架構剖析

E9FACC1D-BEDC-4589-9B8C-578B7A2E6455

 

隨着容器技術的成熟和大規模實踐,基於容器的微服務架構憑藉其對雲服務的天然適應性,以及能夠快速迭代和擴展應用的特點,成爲互聯網創業公司的技術首選。如何更好地利用計算資源?如何更方便地維護越來越複雜的應用程序?由七牛主辦的開發者最佳實踐日第15期,我們邀請到專業CaaS服務提供者靈雀科技的產品經理成然,京東服務平臺資深架構師李鑫和對容器技術有深刻見解的七牛雲技術總監肖勤,和大家一起分享微服務的架構實踐、容器技術的應用,以及對微服務底層的技術框架支持。

 

“微服務+”從理念到行動

 

爲了便於理解微服務的內涵,七牛雲技術總監肖勤先拋出了一個簡單的問題:線上服務器看到很多請求日誌,有成功有失敗,如何統計出成功或者失敗的日誌數量?對此,採用AWK這樣強大的工具,或是採用CUT、SORT這樣的小工具都可以解決問題,而二者在思路上則存在着明顯的差別:AWK是非常強大的工具,在面對複雜的問題時,可以以很多分支和循環的方式去分析和應對;而像CUT、SORT、UNIQ這樣的程序,各自能做的事情非常簡單。比如說把每一行的前幾項分隔開,用SORT做簡單地排序,UNIQ把相同的剝離出來。通過把它們結合起來,一樣可以處理複雜的事情。

 

將這個例子放大到應用和產品層面,就會發現,第二種思路是用一些功能比較明確、業務比較精練的服務去解決更大、更實際的問題,這就是微服務架構的本質。

 

微服務架構基礎案例

 

下圖是一個描述微服務的典型案例。具體場景類似於打車派單類的服務,左邊是採用一個大而全的架構,來處理包括管理司機和乘客,訂單分配和費用支付等所有問題,而右邊是進行拆分,分別採用相對獨立的服務對各方面進行管理,彼此之間使用統一的接口來進行交流。

1

 

從結構來看,右邊的網狀結構其實比左邊星型的結構更復雜,聯繫更多。那麼這樣一個複雜架構的好處表現在哪裏?

 

  • 複雜度可控:在將應用分解的同時,規避了原本複雜度無止境的積累。每一個微服務專注於單一功能,並通過定義良好的接口清晰表述服務邊界。由於體積小、複雜度低,每個微服務可由一個小規模開發團隊完全掌控,易於保持高可維護性和開發效率。
  • 獨立部署:由於微服務具備獨立的運行進程,所以每個微服務也可以獨立部署。當某個微服務發生變更時無需編譯、部署整個應用。由微服務組成的應用相當於具備一系列可並行的發佈流程,使得發佈更加高效,同時降低對生產環境所造成的風險,最終縮短應用交付週期。
  • 技術選型靈活:微服務架構下,技術選型是去中心化的。每個團隊可以根據自身服務的需求和行業發展的現狀,自由選擇最適合的技術棧。由於每個微服務相對簡單,當需要對技術棧進行升級時所面臨的風險較低,甚至完全重構一個微服務也是可行的。
  • 容錯:當某一組建發生故障時,在單一進程的傳統架構下,故障很有可能在進程內擴散,形成應用全局性的不可用。在微服務架構下,故障會被隔離在單個服務中。若設計良好,其他服務可通過重試、平穩退化等機制實現應用層面的容錯。
  • 擴展:單塊架構應用也可以實現橫向擴展,就是將整個應用完整的複製到不同的節點。當應用的不同組件在擴展需求上存在差異時,微服務架構便體現出其靈活性,因爲每個服務可以根據實際需求獨立進行擴展。

 

七牛圖片處理微服務應用案例

 

以七牛雲的圖片處理(簡稱FOP)場景爲例。七牛能夠爲用戶提供格式轉換、尺寸和加水印等圖片處理服務,從而幫助他們節省計算資源和帶寬資源。FOP服務早期的架構很簡單,以它的每一個應用爲後端。但由於原始圖片一般都很大,隨着用戶越來越多,流量越來越高,負載均衡逐漸出現了帶寬和流量的壓力。而面對這種情況,加更多的前端只是權宜之計,因爲圖像處理對於CPU要求很高,意味着後端的數量會越來越多,負載均衡和後端流量方面始終是不平衡的,並且這也不是一個環保和節省資源的方式。

 

於是,FOP服務做了一個架構上的調整:把服務再做拆分。圖像處理服務拆成兩個部分,分別負責處理文件的傳輸和圖像本身的處理。從負載均衡過來的請求不再是完整的文件,而是文件的地址。這樣,我們可以以更靈活來處理,把負載均衡和流量優化,優化和部署也可以跟整個圖像處理沒有關係,可以做單獨的部署。下面兩幅圖即是一個對微服務再進行細分的例子。

2

3

 

而細分之後,對於稍微複雜一些的請求,比如一個圖片需要改變格式和尺寸,並且打上自定義水印。那麼就用管道的方式把不同的服務串聯起來最終實現。

 

容器在微服務中的應用

 

目前微服務架構的主流技術方案中都使用了Docker,七牛也是如此。將Docker理解爲輕量級的虛擬機,它的一些特性如隔離、物理機制等可以說和微服務架構有天然的契合度。但是Docker並不能解決微服務的所有問題,它最初是一個單機的工具,雖然後來官方也推出了很多的工具鏈,要真正解決部署的問題,還有很長的路要走。

 

肖勤推薦了一個去年穀歌發佈的開源容器系統Kubernetes。Kubernetes提供了管理多個容器的方式,能夠令它們在真正的物理機或者虛擬機以一個合理的方式運用起來,供外界訪問。Kubernetes存在的意義,是因爲它解決了微服務另外一個部署的問題,拆分之後不同模塊之間的聯繫和依賴會更加複雜,勢必對於運營和部署有更高的要求,如果沒有工具和系統能夠提供這樣的能力,或者沒有更好的方法去做的話,微服務就是空中樓閣。而Kubernetes提供的能力是用戶只需要去定義它的服務期望的狀態,而不用去關心它的過程。整個調度的過程,整個提供服務的過程都由這個系統去幫你實現。

 

Kubernetes提出了很多概念。比如說Kubernetes Master,它是一箇中心的服務而不是工具。首先由API接受容器的配置,提供一個調度器,把容器調度到合理的位置運行,再提供一定的控制技術,保證容器運行的狀態。Minion可以理解爲容器運行的真正節點,Pods是一個或者一組容器,在Kubernetes 中是可以調動的最小程序,ReplicationController保證了它運行的數據,如果它掛掉了,就不能再提供服務。現在也會有很多服務的副本,以保證Pods的數量和運行狀態。另外一個標籤是Labels,是容器運行時附加的。它的作用是容器在被使用的時候,能夠有一個規則讓前面的服務正確找到它。服務是一個虛擬的概念,是描述一組Pods對外提供的接口和對外提供的能力,通過代理的方式來實現。

 

4

 

上圖是Kubernetes官方文檔中的描述。值得注意的是,Kubernetes系統是按照微服務架構設計的。因爲項目很多部分和逐漸,比如說調度器和複製器,甚至包括Docker在整個系統中都會被替換,如果有更好的容器,Docker有可能會被棄用,變成另外的技術。

 

如何評價Kubernetes系統呢?是不是整個微服務在實踐上的一個未來呢?目前無法確定,因爲從學習的角度上來看, Kubernetes也表現出了一定的侷限性。比如說Pods的網絡,雖然它提供了文檔可以某些方式體現,但是1.0提供的方式還是和自己的雲服務相關。這些侷限性可能跟谷歌的策略有關,因爲谷歌非常希望去推它的GCE平臺。我們發現Kubernetes在設計當中,如果不適用他們的雲服務,摘出來的話,這一部分還需要做很多事情,纔可以把Kubernetes在自己的基礎上做一個比較好的網絡服務。

 

基於Docker的微服務架構雲端實踐

 

應用設計架構的演變

 

十年前想構建一個具備基本功能流程的電子商務網站,包括用戶瀏覽產品信息、加入購物車、下單,在線支付和完成配送,在進行系統構建時,典型做法是把功能模塊簡單地做一些劃分,後臺會訪問統一數據庫,包括用戶管理、商品信息、支付。後來有些程序員意識到可以把一些軟件應用當中的最底層和數據庫獨立起來,緊接着出現了很多的工具做這些東西,如JDBC、ADO.Net等。

 

接下來就出現了比較傳統的經典三層架構Web方式:最上面是展現層,主要是處理UI,中間層處理基本業務,下面是數據訪問層,後面是作爲它的存儲方。如下圖所示。

5

 

時至今日,這種多層次的應用構架仍然具備一些優勢:層次劃分清晰,層與層之間有比較清晰的接口,每層之間非常清晰。展現層只負責UI,邏輯層負責業務邏輯,每一層又可以進而被分解成邏輯的組建。特別是業務邏輯層,一般來說都會把它分爲邏輯組建,包括服務於用戶管理的,服務於產品信息的,服務於支付的,等等。而處於最下面的數據訪問層,雖然能夠被分成若干個模塊和組建,但是從部署上來講,仍然是單塊的組建。所有的程序基本上運行在一個進程上,所有的代碼都會被打包、編譯和部署,我們把它做成一塊的東西。

 

在項目初期,多層架構能夠使程序員更容易開發、測試和部署。但隨着應用程序逐漸增長,業務複雜度會變的越來越高。這種情況下三層構架並不是特別適合業務的繼續發展,可維護性和敏捷程度都會變差,並且團隊擴大後成員之間的溝通也會影響產品的交付。從而最終影響到對市場需求新的跟進。而微服務,就是解決這些問題的一個很好的方案。

 

什麼是微服務

6

 

上圖即爲通過微服務架構把原來的應用拆分成一系列的微服務,它們之間可以用比較輕量級的協議互相溝通,因爲每個服務是運行在自己獨立的進程上,完全可以進行非常獨立的部署和維護。另外一點微服務提倡的是技術選型去中心化,在不同的服務中可以選擇最適合這部分的持久化方案。

 

靈雀雲對已Docker化的微服務的支撐

 

靈雀雲認爲,Docker是運行微服務的最佳解決方案。Docker實際上是一個應用容器的引擎,可以讓開發者非常方便地把自己的應用以及這個應用所需要的所有依賴都打進容器鏡像當中,且具有可移植性,能夠部署到任何服務器上。靈雀雲是基於Docker構建的,如果把封裝的微服務比喻成集裝箱的話,靈雀雲則提供了一個大輪船,裝載了所有集裝箱,爲微服務運行提供一個穩定的運行環境,用戶也可以在此基礎上進行管理。這裏就可以享受到很多雲端服務的優勢。

 

創建:靈雀雲的鏡像構建和持續集成服務幫助用戶將獨立、可複用的微服務打包,轉化爲隨時可以部署的容器鏡像。

集成:靈雀雲不僅在平臺的鏡像倉庫中彙集了大量來自社區的優質鏡像,也支持平臺以外的任意鏡像源。用戶可以自由組合、複用數以萬計的容器化微服務,像搭積木一樣輕鬆集成應用。

部署:微服務由於組件數量衆多,雲端部署成爲實踐上的一個難點。靈雀雲以容器爲應用發佈的載體,用戶不必指定傳統部署方式中繁瑣的步驟,只需提供容器鏡像和簡單的容器配置,平臺會將整個部署流程自動化。靈雀雲與docker-compose兼容,實現對於由多個微服務容器組成的完整應用的一鍵部署。

運維:微服務由於獨立進程衆多,部署後的運維、管理成爲實踐上的另一個難點。靈雀雲完全屏蔽底層雲主機和基礎架構運維,讓用戶專注於應用。同時,靈雀雲通過容器編排、自動修復、自動擴展、監控日誌等高級應用生命週期服務實現容器化微服務的智能託管,進一步幫助用戶降低運維成本和難度。

網絡:微服務架構下各組件之間的溝通、協調對網絡有較高要求,尤其在雲端實踐中,各個微服務組件的物理位置是動態的,且不受應用控制。靈雀雲提供完整的容器網絡解決方案,支持負載均衡、服務發現、跨主機關聯,以及應用安全內網來確保微服務對內、對外網絡的可用性及安全性。

存儲:微服務提倡多元化持久性(Polyglot Persistence),應用內的每個微服務可根據實際需求選擇最合適的數據服務。靈雀雲將持久性雲存儲抽象成數據卷,可以直接掛載在容器上,並在容器重啓、遷移中自動重新掛載。可支持任意容器化數據服務,供微服務應用集成。

 

微服務架構的誕生和容器技術的流行,幾乎是同時發生的,這並不是偶然。這是互聯網時代倒逼傳統技術和架構而產生的變革,最前線的開發者和他們所在的互聯網企業最先感受到了這場變革。靈雀雲希望與開發者一起共同引領這場變革,幫助互聯網企業真正專注於自身的核心業務,並在技術和架構上保持領先。

 

京東對於微服務底層的技術支持實踐

 

京東資深架構師李鑫主要負責京東的服務框架, 他所分享的內容是對微服務底層的技術框架支持。

 

爲何要微服務化?

 

原因有以下幾點。

  • 系統規模隨着業務的發展⽽而增長,原有系統架構模式中邏輯過於耦合,不再適應;
  • 拆分後的⼦系統邏輯內聚,易於局部擴展;
  • ⼦系統之間通過接⼝口來進⾏交互,接⼝契約不變的情況下可獨⽴變化。

7

 

上圖中,左邊是幾年前京東的架構,很多服務都是訪問同樣一個DB。這種架構的問題在於:流量來了以後全部壓力都在DB上。而且在之前京東的架構裏比較強調快速開發,很多邏輯比如說倉儲配送服務都不存在,全都依靠BD來進行。這樣可擴展性相當差,性能也不太可控。後來,我們根據業務模塊和特性進行水平拆分,應用和應用之間都要通過接口進行交互,有同步和異步接口。

 

京東服務平臺演變歷程

 

下圖是京東服務平臺的基本功能構成。

8

在2012年初,京東開始做第一代服務框架,用的是zookeeper集羣作爲註冊中心,baseon開源的服務體系。如下圖所示。

9

第一代架構在運營過程中,暴露出了很多問題。

 

1.客戶端

  • 許多邏輯放到客戶端,客戶端邏輯太多,一旦需要修改,就面臨升級問題。

 

2.註冊中⼼

  • 將ZooKeeper作爲註冊中⼼,功能定製擴展受限。

 

3.服務治理

  • 缺乏流控手段,大流量打爆線程池;
  • 更改配置需要重啓,對於運營不夠友好;
  • 缺乏調用監控,沒有調用分析圖表。

 

爲了解決以上問題,團隊在2014年推出了新服務平臺JSF,其框架示意圖如下。

10

可以看出,服務註冊和尋址沒有太大變化,主要變化在於註冊中心。採用團隊自己寫的服務,並提供了index服務數據庫。相對來講,詢問註冊中心地址,會進行一個服務的調用。因爲這一塊有自己內部的邏輯,沒有辦法實現,所以定期會發送性能統計數據。把RPC轉化,生成負載均衡管理重試策略,然後經過序列化以後發送到server並解碼,再進行實際的業務調用,然後進行一些過濾的邏輯。

 

京東服務平臺核心技術

 

1.協議

  • 採⽤異步事件通訊框架Netty來實現⺴絡協議棧;
  • 同⼀端⼝同時支持Http、TCP協議訪問,根據數據包情況掛載不同解碼器;
  • TCP⻓鏈接下使⽤用⾃定義二進制協議;
  • HTTP⺴關來應對跨語⾔言訪問。

 

2.RPC-callback

  • TCP⻓長鏈接是雙⼯工的,服務⽅方可以主動推送消息到調⽤用⽅方;
  • 調⽤用端檢測到參數列表中有Callback類型,登記相應的callback對象;服務端收到調⽤用時,⽣生成相應的反向調⽤用代理;
  • 服務端持有此代理,並在需要時調⽤用此代理來推送消息。

 

3.負載均衡

一個服務至少部署兩個以上實例,掛了一個以後,另外一個可以正常服務。服務消費者這一塊,有一個負載均衡的算法選擇服務提供者,可以設置權重。有一個可用列表,還有一個重連列,系統會定時連接。還有一個是非健康列表,雖然可以長鏈接建立起來,這個時候給出的反饋是不正常的,維護的時候會把它挪動可用列表裏。

 

4.性能優化

首先有一個批量處理,請求先寫入RingBuffer爲,打成序列化與反序列化這種耗時的操作從Netty的I/O線程中挪到用戶線程池中。啓用壓縮以應對大數據量的請求,默認snappy壓縮算法。最後是定製msgpack序列化,序列化模板,同時還支持fast json、hessian等多種序列化協議。

 

5.註冊中心

京東有很多機房,對於跨機房來說是耗用更多資源,也佔用了專線資源。這裏實現了優先訪問本機房的註冊中心,不可用的話纔會去連起來機房。對於註冊中心來說,後面會連一個數據庫。但是這一塊連數據庫失敗的話,也會有一些單點的問題。對於這種情況,實現了一個LDS,在寫數據庫的同時會寫到本地的存儲,在後臺進行數據的同步。如果說DB服務不可用的話,還是可以取得相應的註冊。

 

6.配置

配置這一塊是服務提供者列表維護,動態推送。可以查看當前服務生效的配置和狀態,可以看出調用的平均耗時和失敗的次數。對服務動態分組無須啓動,而且機房也有備份,出現問題直接調用就可以了。

 

7.限流

每一個服務調用者都有可能成爲潛在的DDOS攻擊者,這裏會給服務的所有調用者帶上標示,在系統環境變量中帶上APPID。此外,開發了計數器服務,限定單位時間內最大調用次數。如果說你是一個推送服務,限定每分鐘四百次,其實調用已經超限了。爲了保護服務端,系統同時限定了併發數,服務端執行時檢查請求的狀態,如等待時間大於超時時間,直接丟棄。

 

8.降級

  • 每個服務接⼝口的每個⽅方法都有災備降級開關;
  • 配置mock邏輯,返回的結果⽤用json格式預先設好;
  • 降級開關打開時將在consumer端短路RPC調⽤用,直接返回JSON結 果。

 

9.彈性雲部署

在京東內部,CAP負責資源調度,JDOS負責資源的虛擬和部署。CAP會定時調度JSF監控平臺的方法,如果說告訴它調用的次數已經超了,CAP會調用JDOS,分配具體的服務資源,把一些新服務自動部署。最終,到註冊中心進行註冊。

 

下一步研發方向

 

首先會做的是服務治理,根據應用ID的一系列管理增強。增強接口文檔管理,建立接口文檔中心,幫助用戶使用接口。最後是增強跨語言支持,對於一些比較小規模的,直接通過網站來更新。

 

以上是牛小七對於本次開發者最佳實踐日內容的概括性介紹,如需獲取詳細的演講信息和往期內容回顧,可以訪問活動專題。瞭解更多關於七牛開發者實踐日,請點擊這裏

發佈了1 篇原創文章 · 獲贊 29 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章