歡迎光臨
每天分享高質量文章

關於微服務架構,你需要關註的那些點

來自:開源中國
https://www.oschina.net/question/2720166_2283418

今天談到系統架構樣式,很難不聯想起微服務架構。企業或組織在系統架構的實踐過程中,從最初的單體架構,之後走向 SOA,逐漸分散式之後,最終產生了微服務架構。

微服務架構的出現,為應對快速變化的業務需求、冗長的開發週期提供了一種新的解決方案,它以模組化的思維應對快速變化的業務需求,解耦系統之間各個子系統、業務、資料庫,甚至開發團隊,使用如自動化部署、自動化業務監控預警、呼叫鏈監控、容器化,以及敏捷開發等思想加快軟體的開發週期,實現更快速、更高質量的交付,成為當下最流行的架構風格之一。

微服務架構如此火熱,開發者想要瞭解其相關知識點,可以透過看書、學習各個公司的實踐經驗,或者請教有經驗的專家,要不就去聽技術會議分享,同時網上也有很多相關理論與實踐總結可以檢視。

而我們之前透過網站上“高手問答”這一欄目,為大家提供了一個集中式向專家提問的機會,讓更多人能夠直接面對專家,提升微服務架構相關能力。當期觀眾提問與專家的回答有許多精彩之處,故整理出此文,以饗讀者。

Q:微服務架構和傳統的 SOA 架構有什麼區別?

面向服務的架構(SOA)是一個元件模型,它將應用程式的不同功能單元(稱為服務)透過這些服務之間定義良好的介面和契約聯絡起來。介面是採用中立的方式進行定義的,它應該獨立於實現服務的硬體平臺、作業系統和程式語言。這使得構建在各種各樣系統中的服務可以以一種統一和通用的方式進行互動。

都是做服務化,那麼微服務與 SOA 的異同有哪些呢?

相同點

  • 需要 Registry,實現動態的服務註冊發現機制。

  • 需要考慮分散式下麵的事務一致性,CAP 原則下,兩段式提交不能保證效能,事務補償機制需要考慮。

  • 同步呼叫還是非同步訊息傳遞,如何保證訊息可靠性?SOA 由 ESB 來整合所有的訊息。

  • 都需要統一的 Gateway 來匯聚、編排介面,實現統一認證機制,對外提供 APP 使用的 RESTful 介面。

  • 同樣要關註如何再分散式下定位系統問題,如何做日誌跟蹤?就像電信領域做了十幾年的信令跟蹤的功能。

    差異點

    • 是持續整合、持續部署?對於 CI、CD(持續整合、持續部署),這本身和敏捷、DevOps 是交織在一起的,所以更傾向於軟體工程的領域而不是微服務技術本身。

    • 使用不同的通訊協議是不是區別?微服務的標桿通訊協議是 RESTful,而傳統的 SOA 一般是 SOAP,不過目前來說採用輕量級的 RPC 框架(Dubbo、Thrift、gRPC)非常多,在 Spring Cloud 中也有 Feign 框架將標準 RESTful 轉為程式碼的 API 這種仿 RPC 的行為,這些通訊協議不應該是區分微服務架構和 SOA 的核心差別。

    • 是流行的基於容器的框架還是虛擬機器為主?Docker 虛擬機器和物理機都是架構實現的一種方式,不是核心區別。

      SOA 和微服務的一個主要不同點就是自動化程度上的不同。大部分的 SOA 實現只達到服務級別的抽象,而微服務達到了對實現和執行環境的抽象級別。

      在一個規範的微服務中,每個微服務應該被構建成胖 JAR(fat JAR),其中內建了所有的依賴,然後作為一個單獨的 Java 行程存在。

      Q:微服務業務層如何進行分層?業務系統如何定級,標準為什麼?

      一般微服務的分層需要根據公司的自身情況。

      同一公司使用統一應用分層,以減少開發維護學習成本。應用分層看起來很簡單,但每個程式員都有自己的一套方法,哪怕是初學者,所以想實施起來並非那麼容易。

      最早接觸的分層架構應該是我們最熟悉的 MVC(Model-View-Controller)架構,其將應用分成了模型、檢視和控制層,可以說引導了絕大多數開發者。而現在的應用(包括框架)中非常多架構設計都使用此樣式。之後又演化出了 MVP(Model-View-Presenter)和 MVVM(Model-View-ViewModel)。這些可以說都是隨著技術的不斷發展,為了應對不同場景所演化出來的模型。

      而微服務的每個架構都可以再細分成領域模型,下麵看一下經典的領域模型架構。

      它包括了 Domain、Service 和 Repositories。核心物體(Entity)和值物件(Value Object)應該在 Domain 層,定義的領域服務(Domain Service)在 Service 層,而針對物體和值物件的儲存和查詢邏輯都應該在 Repositories 層。

      值得註意的是,不要把 Entity 的屬性和行為分離到 Domain 和 Service 兩層中去實現,即所謂的貧血模型,事實證明這樣的實現方式會造成很大的維護問題。基於這種設計,工程的結構可以構造為:

      當然,在微服務的架構中,每個微服務不必嚴格遵照這樣的規定,切忌死搬硬套,最重要的是理解業務。在不同的業務場合,架構的設計可以適當地調整,畢竟適合的架構一定要具有靈活性。

      分層的原則如下:

      檔案夾分層法

      應用分層採用檔案夾方式的優點是可大可小、簡單易用、統一規範,可以包括5個專案,也可以包括50個專案,以滿足所有業務應用的多種不同場景。

      呼叫規約

      在開發過程中,需要遵循分層架構的約束,禁止跨層次的呼叫。

      下層為上層服務

      以使用者為中心,以標的為導向。上層(業務邏輯層)需要什麼,下層(資料訪問層)就提供什麼,而不是下層(資料訪問層)有什麼,就向上層(業務邏輯層)提供什麼。

      物體層規約

      Entity 是資料表物件,不是資料訪問層物件;DTO 是網路傳輸物件,不是表現層物件;BO 是記憶體計算邏輯物件,不是業務邏輯層物件,不是隻能給業務邏輯層使用。如果僅限定在本層訪問,則導致單個應用內大量沒有價值的物件轉換。以使用者為中心來設計物體類,可以減少無價值重覆物件和無用轉換。

      U型訪問

      下行時表現層是 Input,業務邏輯層是 Process,資料訪問層是 Output。上行時資料訪問層是 Input,業務邏輯層是 Process,表現層是 Output。

      Q:微服務的粒度到底怎麼劃分,有什麼經驗嗎?

      這個也是個設計問題,首先是業務必須熟悉,然後可以根據領域模型進行領域劃分,拆分可以根據 AKF 擴充套件立方體(Scalability Cube)。

      這個立方體有三個軸線,每個軸線描述擴充套件性的一個維度,他們分別是產品、流程和團隊:

      • X軸 —— 代表無差別的克隆服務和資料,工作可以很均勻的分散在不同的服務實體上;

      • Y軸 —— 關註應用中職責的劃分,比如資料型別,交易執行型別的劃分;

      • Z軸 —— 關註服務和資料的優先順序劃分,如分地域劃分。

      

      三個維度擴充套件的對比

      透過這三個維度上的擴充套件,可以快速提高產品的擴充套件能力,適應不同場景下產品的快速增長。不同維度上的擴充套件,有著不同的優缺點:

      X軸擴充套件

      • 優點:成本最低,實施簡單;

      • 缺點:受指令集多少和資料集大小的約束。當單個產品或應用過大時,服務響應變慢,無法透過X軸的水平擴充套件提高速度;

      • 場景:發展初期,業務複雜度低,需要增加系統容量。

      Y軸擴充套件

      • 優點:可以解決指令集和資料集的約束,解決程式碼複雜度問題,可以實現隔離故障,可以提高響應時間,可以使團隊聚焦更利於團隊成長;

      • 缺點:成本相對較高;

      • 場景:業務複雜,資料量大,程式碼耦合度高,團隊規模大。

      Z軸擴充套件

      • 優點:能解決資料集的約束,降低故障風險,實現漸進交付,可以帶來最大的擴充套件性。

      • 缺點:成本最昂貴,且不一定能解決指令集的問題;

      • 場景:使用者指數級快速增長。

        如何將理論付諸實踐?

        為擴充套件分割應用

        • X軸:從單體系統或服務,水平克隆出許多系統,透過負載均衡平均分配請求;

        • Y軸 :面向服務分割,基於功能或者服務分割,例如電商網站可以將登陸、搜尋、下單等服務進行Y軸的拆分,每一組服務再進行X軸的擴充套件;

        • Z軸 :面向查詢分割,基於使用者、請求或者資料分割,例如可以將不同產品的SKU分到不同的搜尋服務,可以將使用者雜湊到不同的服務等。

          為擴充套件分割資料庫 

          • X軸:從單庫,水平克隆為多個庫上讀,一個庫寫,透過資料庫的自我複製實現,要允許一定的讀寫時延;

          • Y軸 :根據不同的資訊型別,分割為不同的資料庫,即分庫,例如產品庫,使用者庫等;

          • Z軸 :按照一定演演算法,進行分片,例如將搜尋按照MapReduce的原理進行分片,把SKU的資料按照不同的雜湊值進行分片儲存,每個分片再進行X軸冗餘。

            為擴充套件而快取

            在理想情況下,處理大流量最好的方法是透過高速快取來避免處理它。從架構層面看,我們能控制的主要有以下三個層次的快取:

            • 物件快取:物件快取用來儲存應用的物件以供重覆使用,一般在系統內部,透過使用應用快取可以幫助資料庫和應用層解除安裝負載。

            • 應用快取:應用快取包括代理快取和反向代理快取,一個在使用者端,一個在服務端,標的是提高效能或減少資源的使用量。

            • 內容交付網路快取:CDN 的總原則是將內容推送到盡可能接近使用者終端的地方,透過不同地區使用不同ISP的閘道器快取,達到更快的響應時間和對源服務的更少請求。

              為擴充套件而非同步

              • 同步改非同步:同步呼叫,由於呼叫間的同步依賴關係,有可能會導致雪崩效應,出現一系列的連鎖故障,進而導致整個系統出現問題,所以在進行系統設計時,要盡可能的考慮非同步呼叫方式,郵件系統就是一個非常好的非同步呼叫例子。

              • 應用無狀態:當進行 AKF 擴充套件立方體的任何一個軸上的擴充套件時,都要首先解決應用的狀態問題,即會話的管理,可以透過避免、集中和分散的方式進行解決。

              Q:微服務怎麼實現事務管理的?

              其實微服務的事務就是分散式事務,剛性事務和柔性事務。

              剛性事務是指嚴格遵循 ACID 原則的事務,例如單機環境下的資料庫事務。柔性事務是指遵循 BASE 理論的事務,通常用在分散式環境中,常見的實現方式有:兩階段提交(2PC),TCC 補償型提交,基於訊息的非同步確保型,最大努力通知型。

              資料一致性分為以下幾種情況:

              強一致性

              當更新操作完成之後,任何多個後續行程或者執行緒的訪問都會傳回最新的更新過的值。這種是對使用者最友好的,就是使用者上一次寫什麼,下一次就保證能讀到什麼。根據 CAP 理論,這種實現需要犧牲可用性。

              弱一致性

              系統並不保證後續行程或者執行緒的訪問都會傳回最新的更新過的值。系統在資料寫入成功之後,不承諾立即可以讀到最新寫入的值,也不會具體地承諾多久之後可以讀到。

              最終一致性

              弱一致性的特定形式。系統保證在沒有後續更新的前提下,系統最終傳回上一次更新操作的值。在沒有故障發生的前提下,不一致視窗的時間主要受通訊延遲、系統負載和複製副本的個數影響。DNS 是一個典型的最終一致性系統。

              分散式事務的各種實現方式:

              • 如果業務場景需要強一致性,那麼儘量避免將它們放在不同服務中,也就是儘量使用本地事務,避免使用強一致性的分散式事務。

              • 如果業務場景能夠接受最終一致性,那麼最好是使用基於訊息的最終一致性的方案(非同步確保型)來解決。

              • 如果業務場景需要強一致性,並且只能夠進行分散式服務部署,那麼最好是使用 TCC 方案而不是 2PC 方案來解決。

              Q:在基於 Spring Cloud 的微服務架構中,使用 Docker 和 k8s 這些容器化技術能帶來哪些方面的好處?對於中小規模的微服務架構中,是否有使用它們的必要性呢?

              容器技術不是模仿硬體層次,而是在 Linux 核心裡使用 cgroup 和 namespaces 來打造輕便的、將近裸機速度的虛擬技術作業系統環境。因為不是虛擬化儲存,所以容器技術不會管底層儲存或者檔案系統,而是你放哪裡,它操作哪裡。

              也就是說,它能更細粒度地控制 Linux,能夠做到按需分配,我們企業級開發種經常面臨的一個問題就是資源不足,而使用 Docker 可以更加有效地利用資源。這個跟企業的規模個人感覺不是很大。

              Q:微服務樣式下資料庫的管理,多個服務之間的資料聚合怎麼做才能避免資料過於分散導致查詢實現困難?感覺 k8s 可以代替 Spring Cloud 的一些元件(比如均衡負載、配置服務、服務發現),如何才能分清它們之間的關係?

              資料聚合其實涉及到微服務的一種設計樣式,微服務的設計樣式主要有以下幾種:鏈式設計樣式、聚合器設計樣式、資料共享設計樣式和非同步訊息控制樣式。

              聚合器設計樣式是將請求統一由閘道器路由到聚合器,聚合器向下路由到指定的微服務中獲取結果,並且完成聚合。首頁展現、分類搜尋和個人中心等通常都使用這種設計。

              

              資料共享樣式也是微服務設計樣式的一種。應用透過閘道器呼叫多個微服務,微服務之間的資料共享透過同一個資料庫,這樣能夠有效地減少請求次數,並且對於某些資料量小的情況非常適合。

              

              也就是說,服務需要經過一定的設計處理。可以再閘道器部分實現資料查詢的路由。

              說到 k8s 和 Spring Cloud,兩個平臺在核心領域都很強,並且在其它領域改進。Spring Cloud 可以快速使用、對開發者友好,然而 Kubernetes 對 DevOps 友好,艱難的學習曲線,但是改寫更廣泛的微服務障礙。以下是這些點的總結。

              

              兩種架構處理了不同範圍的 MSA 障礙,並且它們從根本上用了不同的方法。Spring Cloud 方法是試圖解決在 JVM 中每個 MSA 挑戰,而 Kubernetes 方法是試圖讓問題消失,為開發者在平臺層解決。Spring Cloud 在 JVM 中非常強大,Kubernetes 管理那些 JVM 很強大。同樣的,它就像一個自然發展,結合兩種工具並且從兩個專案中最好的部分受益。

              Q:請教一下,關於微服務架構中的 Service Mesh,它有哪些優勢呢?

              Service Mesh 最終並不是引入一項新功能,而是功能定位的轉變。首先我們要知道 Web 應用程式總是必須管理服務間通訊的複雜性。

              Service Mesh 是一個網路模型,它是位於 TCP/IP 之上的抽象層,它假定底層的 L3/L4 網路是真實存在的,並且能夠點對點地傳遞位元組。但與 TCP 不同的是,Service Mesh 具有更高的效能。

              它以專用基礎設施層的形式存在,通常作為一組輕量級高效能網路代理,這些代理和程式程式碼部署在一起,但是應用程式不需要對代理有任何動作,它被用來處理服務間通訊,透過複雜的拓撲結構讓請求傳遞的過程變得更可靠。

              你可以思考下2000年的中型 Web 應用程式的典型架構: 三層應用程式。 在這個模型中,應用程式邏輯、Web 服務邏輯和儲存邏輯都是單獨的一層,層之間的通訊雖然複雜,但這種複雜性是限定在一定範圍內,因為畢竟只有兩個跳轉。這裡沒有“網格”(Mesh),但是在每個層的程式碼中處理的跳轉之間有通訊邏輯。

              當這種架構方式在面對應用程式內部邏輯越來越複雜化的情形時,它就開始崩潰了。 像 Google、Netflix 和 Twitter 這樣的公司無時無刻都面臨著巨大的流量需求,它們實現了雲原生方案的前身:應用層被分解成許多服務(有時稱為“微服務”),層級間則形成了一個拓撲結構。

              在這些系統中,廣義的通訊層突然變得相關起來,但通常以“胖客戶端”的庫集(library)形式出現, 比如 Twitter 的 Finagle、Netflix 的 Hystrix,以及 Google 的 Stubby 就是這樣的例子。

              從很多方面上來講,像 Finagle、Stubby 和 Hystrix 這些庫集其實是 Service Mesh 的雛形。雖然它們受其周圍環境的細節影響,並且需要使用特定的語言和框架,但是它們是用於管理服務到服務間通訊的專用基礎設施,並且(在開源 Finagle 和 Hystrix 庫集的情形下)可以在其公司之外使用。

              到了雲原生應用時期,雲原生模型本身結合了許多小型服務的微服務方法和兩個額外的因素:容器(例如 Docker),它提供了資源隔離和依賴關係管理,以及一個編排層(例如 Kubernetes),它將底層硬體抽象出了一個同質池。

              這三個元件支援應用程式在負載下可彈性伸縮的自然機制, 並能夠處理雲平臺環境中存在的部分故障。

              但面對數百個服務或數千個實體,和隨時在重新安排實體的編排層,單個請求經由服務拓撲的路徑可能非常複雜,而由於容器使每個服務用不同的語言寫入處理變得更容易了,庫集方法也就不再可行了。

              這種複雜性和關鍵性的結合,激發了對服務到服務間通訊的專用基礎層的需求,這個專用層與應用程式程式碼分離出來,並能夠捕捉底層環境的高度動態特性。就是這一專用層我們稱之為 Service Mesh。這樣 Service Mesh 的優勢自然也就可以瞭解了。

              Q:我是來自於一家中小企業的運維和開發人員,一直對微服務架構很感興趣,請問一下如果我們企業將來打算採用微服務架構,我們將面臨著哪些挑戰?

              面臨的挑戰:

              • 思想的轉變。首先要徹底地理解什麼是微服務,要知道它相比單體架構、SOA 架構的不同是什麼、優劣是什麼,具體如何落地等問題。

              • 新技術以及新框架的學習。比如spring boot、docker等。

                一些建議:

                • 透過查閱相關資料,對傳統架構和微服務架構的區別以及演變流程,可以首先有一個概念性的瞭解。

                • 可以先讓一部分人使用微服務架構並且做到深入的程度,然後再在企業中整體推廣。

                篇幅限制,只截取了部分,完整內容可以點選下方“閱讀原文”檢視。


                嘉賓:張鋒,《微服務架構實戰》一書作者,北京航空航天大學軟體工程碩士,資深架構師,有10多年管理和架構經驗,在業界頗具威望和影響力。曾就職於神州資料、亞信科技、中文線上及多家網際網路公司,擔任架構師及技術總監等職位,現在就職於中青旅,任架構組組長,成功管理和指導過三農綜合服務資訊平臺、西北企業雲服務平臺、省級電信平臺及多個網際網路平臺的架構升級改造。擁有工信部認證高階資訊系統專案管理師資格。


                ●編號767,輸入編號直達本文

                ●輸入m獲取文章目錄

                推薦↓↓↓

                演演算法與資料結構

                更多推薦18個技術類公眾微信

                涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。

贊(0)

分享創造快樂