微服務軟體架構的認識和設計模式

来源:http://www.cnblogs.com/linezero/archive/2017/02/06/microservices.html
-Advertisement-
Play Games

什麼是微服務? 微服務存在多種定義。 如果搜索 Internet,會發現許多有用的資源,這些資源提供了自己的觀點和定義。 但在微服務的以下大部分特性上,已廣泛達成共識: 封裝客戶方案或業務方案。 你要解決什麼問題? 由小型工程團隊開發。 使用任何編程語言編寫並使用任何框架。 由獨立控製版本、部署及縮 ...


什麼是微服務?

微服務存在多種定義。 如果搜索 Internet,會發現許多有用的資源,這些資源提供了自己的觀點和定義。 但在微服務的以下大部分特性上,已廣泛達成共識:

  • 封裝客戶方案或業務方案。 你要解決什麼問題?
  • 由小型工程團隊開發。
  • 使用任何編程語言編寫並使用任何框架。
  • 由獨立控製版本、部署及縮放的代碼和(可選)狀態組成。
  • 通過定義完善的介面和協議來與其他微服務交互。
  • 具有用來解析位置的唯一名稱 (URL)。
  • 在出現故障時可保持一致且可用。

一言以蔽之:

微服務應用程式由獨立控製版本和可縮放的、以客戶為中心的服務組成,這些服務通過標準協議和定義完善的介面彼此通信。

 

微服務(micro services)這個概念不是新概念,很多公司已經在實踐了,例如亞馬遜、Google、FaceBook,Alibaba。微服務架構模式(Microservices Architecture Pattern)的目的是將大型的、複雜的、長期運行的應用程式構建為一組相互配合的服務,每個服務都可以很容易得局部改良。 Micro這個詞意味著每個服務都應該足夠小,但是,這裡的小不能用代碼量來比較,而應該是從業務邏輯上比較——符合SRP原則的才叫微服務。

微服務跟SOA有什麼區別呢,可以把微服務當做去除了ESB的SOA。ESB是SOA架構中的中心匯流排,設計圖形應該是星形的,而微服務是去中心化的分散式軟體架構。

接下來會討論以下幾個話題:

應用微服務的動機,跟傳統巨石應用的比較
微服務的優點與缺點
應用微服務架構設計時可能遇到的關鍵問題(內部服務通信、分散式數據管理)


一、巨石(monolith)

web應用程式發展的早期,大部分web工程是將所有的功能模塊(service side)打包到一起並放在一個web容器中運行,很多企業的Java應用程式打包為war包。其他語言(Ruby,Python或者C++)寫的程式也有類似的問題。

假設你正在構建一個線上商店系統:客戶下訂單、核對清單和信用卡額度,並將貨物運輸給客戶。很快,你們團隊一定能構造出如下圖所示的系統。

 


the monolithic architecture
這種將所有功能都部署在一個web容器中運行的系統就叫做巨石型應用。巨石型應用有很多好處:IDE都是為開發單個應用設計的、容易測試——在本地就可以啟動完整的系統、容易部署——直接打包為一個完整的包,拷貝到web容器的某個目錄下即可運行。

但是,上述的好處是有條件的:應用不那麼複雜。對於大規模的複雜應用,巨石型應用會顯得特別笨重:要修改一個地方就要將整個應用全部部署(PS:在不同的場景下優勢也變成了劣勢);編譯時間過長;回歸測試周期過長;開發效率降低等。另外,巨石應用不利於更新技術框架,除非你願意將系統全部重寫(代價太高你願意老闆也不願意)。

二、應用拆分

詳細一個網站在業務大規模爬升時會發生什麼事情?併發度不夠?OK,加web伺服器。資料庫壓力過大?OK,買更大更貴的資料庫。資料庫太貴了?將一個表的數據分開存儲,俗稱“分庫分表”。這些都沒有問題,good job。不過,老外的抽象能力比我們強,看下圖。

 

the scale cube

這張圖從三個維度概括了一個系統的擴展過程:(1)x軸,水平複製,即在負載均衡伺服器後增加多個web伺服器;(2)z軸擴展,是對資料庫的擴展,即分庫分表(分庫是將關係緊密的表放在一臺資料庫伺服器上,分表是因為一張表的數據太多,需要將一張表的數據通過hash放在不同的資料庫伺服器上);(3)y軸擴展,是功能分解,將不同職能的模塊分成不同的服務。從y軸這個方向擴展,才能將巨型應用分解為一組不同的服務,例如訂單管理中心、客戶信息管理中心、商品管理中心等等。

將系統劃分為不同的服務有很多方法:(1)按照用例劃分,例如線上商店系統中會劃分出一個checkout UI服務,這個服務實現了checkout這個用例;(2)按照資源劃分,例如可以劃分出一個catlog服務來存儲產品目錄。

服務劃分有兩個原則要遵循:(1)每個服務應該儘可能符合單一職責原則——Single Responsible Principle,即每個服務只做一件事,並把這件事做好;(2)參考Unix命令行工具的設計,Unix提供了大量的簡單易用的工具,例如grep、cat和find。每個工具都小而美。

最後還要強調:系統分解的目標並不僅僅是搞出一堆很小的服務,這不是目標;真正的目標是解決巨石型應用在業務急劇增長時遇到的問題。

對於上面的例子,按照功能和資源劃分後,就形成下麵圖的架構圖。分解後的微服務架構包含多個前端服務和後端服務。前端服務包括Catalog UI(用於商品搜索和瀏覽)、Checkout UI(用於實現購物車和下單操作);後端服務包括一些業務邏輯模塊,我們將在巨石應用中的每個服務模塊重構為一個單獨的服務。這麼做有什麼問題呢?

 


the microservice architecture


三、微服務架構的優點與缺點

1. 優點

每個服務足夠內聚,足夠小,代碼容易理解、開發效率提高
服務之間可以獨立部署,微服務架構讓持續部署成為可能;
每個服務可以各自進行x擴展和z擴展,而且,每個服務可以根據自己的需要部署到合適的硬體伺服器上;
容易擴大開發團隊,可以針對每個服務(service)組件開發團隊;
提高容錯性(fault isolation),一個服務的記憶體泄露並不會讓整個系統癱瘓;
系統不會被長期限制在某個技術棧上。
2. 缺點

《人月神話》中講到:沒有銀彈,意思是只靠一把錘子是蓋不起摩天大樓的,要根據業務場景選擇設計思路和實現工具。我們看下為了換回上面提到的好處,我們付出(trade)了什麼?

開發人員要處理分散式系統的複雜性;
開發人員要設計服務之間的通信機制,對於需要多個後端服務的user case,要在沒有分散式事務的情況下實現代碼非常困難;
涉及多個服務直接的自動化測試也具備相當的挑戰性;
服務管理的複雜性,在生產環境中要管理多個不同的服務的實例,這意味著開發團隊需要全局統籌(PS:現在docker的出現適合解決這個問題)
應用微服務架構的時機如何把握?對於業務還沒有理清楚、業務數據和處理能力還沒有開始爆髮式增長之前的創業公司,不需要考慮微服務架構模式,這時候最重要的是快速開發、快速部署、快速試錯。

 

四、微服務架構的關鍵問題

1. 微服務架構的通信機制

(1)客戶端與伺服器之間的通信

在巨石型架構下,客戶端應用程式(web或者app)通過向服務端發送HTTP請求;但是,在微服務架構下,原來的巨石型伺服器被一組微服務替代,這種情況下客戶端如何發起請求呢?

如圖中所示,客戶端可以向micro service發起RESTful HTTP請求,但是會有這種情況發生:客戶端為了完成一個業務邏輯,需要發起多個HTTP請求,從而造成系統的吞吐率下降,再加上無線網路的延遲高,會嚴重影響客戶端的用戶體驗。

 


calling services directly
為瞭解決這個問題,一般會在伺服器集群前面再加一個角色:API gateway,由它負責與客戶度對接,並將客戶端的請求轉化成對內部服務的一系列調用。這樣做還有個好處是,服務升級不會影響到客戶端,只需要修改API gateway即可。加了API gateway之後的系統架構圖如圖5所示。

 


API gateway
(2)內部服務之間的通信

內部服務之間的通信方式有兩種:基於HTTP協議的同步機制(REST、RPC);基於消息隊列的非同步消息處理機制(AMQP-based message broker)。

Dubbo是阿裡巴巴開源的分散式服務框架,屬於同步調用,當一個系統的服務太多時,需要一個註冊中心來處理服務發現問題,例如使用ZooKeeper這類配置伺服器進行服務的地址管理:服務的發佈者要向ZooKeeper發送請求,將自己的服務地址和函數名稱等信息記錄在案;服務的調用者要知道服務的相關信息,具體的機器地址在ZooKeeper查詢得到。這種同步的調用機制足夠直觀簡單,只是沒有“訂閱——推送”機制。

AMQP-based的代表系統是kafka、RabbitMQ等。這類分散式消息處理系統將訂閱者和消費者解耦合,消息的生產者不需要消費者一直線上;消息的生產者只需要把消息發送給消息代理,因此也不需要服務發現機制。

兩種通信機制都有各自的優點和缺點,實際中的系統經常包含兩種通信機制。例如,在分散式數據管理中,就需要同時用到同步HTTP機制和非同步消息處理機制。

2. 分散式數據管理

(1)處理讀請求

線上商店的客戶賬戶有限額,當客戶試圖下單時,系統必須判斷總的訂單金額是否超過他的信用卡額度。信用卡額度由CustomerService管理、下訂單的操作由OrderService負責,因此Order Service要通過RPC調用向Customer Service請求數據;這種方法能夠保證每次Order Service都獲取到準確的額度,單缺點是多一次RPC調用、而且Customer Service必須保持線上。

還有一種處理方式是,在OrderService這邊存放一份信用卡額度的副本,這樣就不需要實時發起RPC請求,但是還需要一種機制保證——當Customer Service擁有的信用卡額度發生變化時,要及時更新存放在Order Service這邊的副本。

(2)處理更新請求

當一份數據位於多個服務上時,必須保證數據的一致性。

分散式事務(Distributed transactions)
使用分散式事務非常直觀,即要更新Customer Service上的信用卡額度,就必須同時更新其他服務上的副本,這些操作要麼全做要麼全不做。使用分散式事務能夠保證數據的強一致,但是會降低系統的可用性——所有相關的服務必須始終線上;而且,很多現代的技術棧並不支持事務,例如REST、NoSQL資料庫等。
基於事件的非同步更新(Event-driven asynchronous updates)
Customer Service中的信用卡額度改變時,它對外發佈一個事件到“message broker(消息代理人)”;其他訂閱了這個事件的服務受到提示後就更新數據。事件流如圖所示。

 

replicating the credit limit using events

 

六種微服務架構的設計模式

聚合器微服務設計模式

這是一種最常用也最簡單的設計模式,如下圖所示:

 

 

聚合器調用多個服務實現應用程式所需的功能。它可以是一個簡單的Web頁面,將檢索到的數據進行處理展示。它也可以是一個更高層次的組合微服務,對檢索到的數據增加業務邏輯後進一步發佈成一個新的微服務,這符合DRY原則。另外,每個服務都有自己的緩存和資料庫。如果聚合器是一個組合服務,那麼它也有自己的緩存和資料庫。聚合器可以沿X軸和Z軸獨立擴展。

代理微服務設計模式

這是聚合器模式的一個變種,如下圖所示:

 

 

在這種情況下,客戶端並不聚合數據,但會根據業務需求的差別調用不同的微服務。代理可以僅僅委派請求,也可以進行數據轉換工作。

鏈式微服務設計模式

這種模式在接收到請求後會產生一個經過合併的響應,如下圖所示:

 

 

在這種情況下,服務A接收到請求後會與服務B進行通信,類似地,服務B會同服務C進行通信。所有服務都使用同步消息傳遞。在整個鏈式調用完成之前,客戶端會一直阻塞。因此,服務調用鏈不宜過長,以免客戶端長時間等待。

分支微服務設計模式

這種模式是聚合器模式的擴展,允許同時調用兩個微服務鏈,如下圖所示:

 

 

數據共用微服務設計模式

自治是微服務的設計原則之一,就是說微服務是全棧式服務。但在重構現有的“單體應用(monolithic application)”時,SQL資料庫反規範化可能會導致數據重覆和不一致。因此,在單體應用到微服務架構的過渡階段,可以使用這種設計模式,如下圖所示:

 

 

在這種情況下,部分微服務可能會共用緩存和資料庫存儲。不過,這隻有在兩個服務之間存在強耦合關係時才可以。對於基於微服務的新建應用程式而言,這是一種反模式。

非同步消息傳遞微服務設計模式

雖然REST設計模式非常流行,但它是同步的,會造成阻塞。因此部分基於微服務的架構可能會選擇使用消息隊列代替REST請求/響應,如下圖所示:

 

 

 

參考文檔:http://www.jianshu.com/p/546ef242b6a3

       http://www.infoq.com/cn/news/2015/04/micro-service-architecture

     https://docs.microsoft.com/zh-cn/azure/service-fabric/service-fabric-overview-microservices


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一:漢化框架 框架漢化在這裡設置,如果不生效,前臺後臺的配置文件都設置下應該就可以了 二:漢化表單 漢化表單,直接在模型層設置,例如: 原來的聯繫我們表單 漢化後: 】 這種漢化在哪裡修改呢?其實是設置屬性標簽,設置位置在模型層 代碼如下 設置位置截圖 ...
  • 一、 面向對象,這個對象到底是什麼? 這個對象不是C#中的實例,C#中我們把一個類的實例也叫做對象,這種對象嚴格的說應該是面向對象的編程實現(OOP)中的對象,面向對象編程,也不是面向類的實例編程。對象的定義是人們要進行研究的任何事物,從最簡單的整數到複雜的飛機等均可看作對象,它不僅能表示具體的事物 ...
  • 今天,我們來講備忘錄模式 一、案例: 小伙伴們都玩過單機游戲或者說RPG類的游戲吧,我們在打BOSS之前,需要先存一下檔,以免BOSS打不過從頭再來,好,下麵,我們用簡單的控制台應用程式來描述一下這個場景。 客戶端調用: 好了,我們很好的描述了我們案例中的場景,那下麵,我們看一下我們這段代碼有什麼不 ...
  • 什麼是微服務 一些協同工作的小而自治的服務 微服務的優點 技術異構性 彈性 擴展性 簡化部署 對可替代性的優化 微服務的原則 原則舉例 ...
  • Netty 提供非同步的、事件驅動的網路應用程式框架和工具,用以快速開發高性能、高可靠性的網路伺服器和客戶端程式 本文對Netty做了一個總體概覽 ...
  • 今天我們來講一下適配器模式。下麵,我們描述一個場景: 不管是籃球隊還是足球隊,都會有外援的,在隊內訓練與安排戰術的時候,外援可能聽不懂漢語的,那麼,他們怎麼交流呢,這就需要一個翻譯了。其實,這個翻譯就起到了一個適配器的效果。 何為適配器模式:將一個介面轉換成為客戶希望的另外一個介面,使得原本由於介面 ...
  • 閱讀目錄 前言 回顧 本地的一致性 領域事件發佈出現異常 訂閱者處理出現異常 結語 一、前言 上篇中我們初步運用了領域事件,其中還有一些問題我們沒有解決,所以實現是不健壯的,下麵先來回顧一下。 二、回顧 先貼一下上篇中的遺留的問題: 不知道大家有沒有發現這裡代碼上的一個問題,就是DomainEven ...
  • 今天我們來將狀態模式,首先,我們來描述下麵一個場景: 一、案例: 在工作過程中,根據時間段的不同,我們工作的狀態也有所不同,下麵,我們用簡單的控制台應用程式,來實現一下這個場景。 客戶端 二、演繹 1、第一步演繹 看到上面用代碼描述的場景,對於我們學了好多設計模式的小伙伴來講,是不是顯得特別的挫,最 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...