【編者的話】 本文從對微服務的誤解誤用切入,探討什麼是微服務,如何切分微服務。提出告終合傳統的DDD,領域驅動設計的理念來幫助定義微服務的邊界,值得一讀。數據庫
過去的三年裏,個人工做是Golang,以及雲原生的分佈式系統架構,包括微服務的諮詢師和培訓師。在微服務的諮詢經驗裏,在不一樣的客戶那裏由於你們對微服務的誤解,我遇到過不少奇怪的事情。我在印度工做,至少在這裏,微服務是當下IT行業裏最被誤解的技術。每一個人都在談微服務。不少人說他們的應用程序是基於微服務架構的。api
這裏有幾種我據說過的微服務相關的誤解:安全
有關微服務的誤解還有不少不少不在上述列表中。你可能會使用上述列表裏的一些技術來構建微服務,可是使用了某些工具和框架就說本身是微服務,這是沒有道理的。網絡
微服務是分佈式的系統架構,可是那些歷來沒有開發過度布式系統的開發團隊,正在試圖像學習新框架那樣來學習它,而且基於一些誤解來構建應用程序,而後聲稱本身的應用是基於微服務的。能夠看到不少文章的標題都是使用X(Go,Node.js,Java等等)語言,Docker和Kubernetes來構建微服務,講解構建HTTP服務,在Docker容器裏運行,而且使用Kubernetes管理集羣,認爲這就是微服務。最近在一次個人微服務培訓裏,一個認爲本身是頗有經驗的架構師的人,告訴我他是微服務大師,知道有關微服務的全部東西。在我和他的討論中,我意識到他歷來沒有據說過DDD和Bounded Context, Event Sourcing, CQRS, gRPC等等,都是從我這裏第一次聽到這些詞。一個歷來沒有據說過領域建模和DDD Bounded Context的人認爲本身是微服務的超級大師。。。架構
和我探討過的不少創業公司,都宣傳他們遵照微服務架構。在和他們的討論中,我意識到他們稱其爲微服務,是由於他們的產品有2-5個運行着的應用程序,對於他們來講每一個應用程序就是一個微服務。面向客戶的應用程序是一個微服務,管理應用是另外一個微服務,後臺worker是微服務,RESTful API是另外一個微服務。你們基於本身的理解以及本身習慣的方式來構建本身的微服務。讓人傷心的是有人甚至沒有意識到微服務是一種分佈式系統架構。框架
首先最爲重要的是,微服務是構建分佈式系統的架構風格。微服務解決了構建分佈式系統的複雜度。在微服務架構裏,軟件系統由一系列互相獨立可部署,小的,模塊化的服務組成。每一個微服務圍繞一種小型業務能力而構建,由獨立團隊管理。微服務是某個小型業務能力的獨立可部署的組件,微服務架構是構建高度可擴展可進化的軟件系統的工程風格,由細粒度的微服務組成。直觀上,微服務是能夠一塊兒工做的小的,自治的服務。異步
在絕大多數狀況下,一開始應用程序是個單體應用,全部業務能力都放在單個應用程序裏,運行在單個進程裏。這樣的應用程序很容易開發,可是很難有效地擴展,由於應用程序的每一個組件都緊耦合在一塊兒。在微服務的架構裏,咱們經過組合一系列的自治服務來構建應用程序,每一個服務運行在本身的進程裏。這樣,就能夠很輕鬆地實現擴展——能夠給不一樣的服務賦予不一樣的擴展能力,獨立地升級而且替代每一個服務,同時得到不少其餘的架構優點。編程語言
不少人認爲微服務是統一的架構框架,是解決全部軟件工程問題的銀彈。所以你們問的問題相似於,微服務的安全是什麼樣的。微服務並不是一種統一的架構框架,並非軟件工程中全部問題的解決方案,可是它是構建分佈式系統的一種方式,這裏的核心思想是服務模塊化。也就是說,微服務是構建分佈式系統的一種思路,須要多種架構方案來實現這樣的思路。微服務是已經使用好久的多種架構方案的演進。所以在真實的微服務裏,你仍然會使用以前使用過的多種架構方案。分佈式
容器化是構建而且運行微服務的很好的方式。若是能夠將微服務打包進容器,那麼就能夠無限擴展而且動態編排微服務,而不需考慮在哪裏運行。打包工具,好比Docker,rkt和編排工具,好比Kubernetes,都是容器化微服務的很好的技術。
當從單體架構向微服務架構演進時,最大的問題是怎麼將微服務分離出來。如何將一個大型軟件系統分解爲功能性的組件?微服務的規模多大合適?答案很簡單:領域建模。Sam Newman,在他的書「構建微服務」裏說,全部走向微服務的路都繞不開領域建模。Eric Evans寫的在2003年出版的「領域驅動設計:在軟件核內心處理複雜度」是領域建模領域的經典書籍,提供了基於領域模型構建複雜軟件系統的指導概要。自從這本書出版以後,Domain-Driven Design (DDD,領域驅動設計)這一術語被業界普遍接受,而且開始使用DDD做爲構建軟件系統的方式。DDD,介紹了多種構建塊,好比Entity,Value Object,Service,Repository,Aggregate和Bounded Context。
Aggregate和Bounded Context是構建微服務的構建塊,將決定單個微服務的大小。一般業務實體,好比Order,Customer,Account是Aggregate,它是一張圖,包含根實體以及一個或多個其餘實體和value對象,是一個最小單元。在微服務裏執行事務的更好的方式是經過aggregate實現持久化。Bounded Context是DDD的核心模式,經過將大模型分解爲不一樣的Bounded Context,從而將業務問題從邏輯上分解成多個子域。Bounded Context封裝了單個領域的細節,大型領域模型的子域,就能夠剝離爲單個微服務。構建微服務的常見戰略就是基於每一個Bounded Context構建微服務。每一個微服務使用本身的數據庫來持久化某個領域模型的Bounded Context。單個Bounded Context能夠包含不少aggregate root,或者單個Bounded Context能夠包含一個aggregate root。Order的aggregate root,包含實體包括OrderLine,Customer和Product,value object包括ShippingAdress,PaymentMethod等。在Order的aggregate root圖裏,Customer實體還能夠做爲aggregate root,由於它能夠做爲root實體,獲得某個客戶的全部信息。Aggregate和Bounded Context是微服務架構裏的重要概念,這是構建微服務的基礎塊,也將決定微服務的大小。簡單來講,微服務是圍繞Bounded Context的自治服務。
微服務架構的確是構建分佈式系統的絕佳方案。可是要記住微服務既不是銀彈也不是一種簡單的方案。即便使用了微服務來下降構建分佈式系統的複雜度,構建分佈式系統也毫不是一件輕鬆的事情。
當從單體應用程序轉向微服務架構時,須要解決不少實際的挑戰。好比,業務事務可能會分散爲幾個微服務,由於基於Bounded Context將單體系統分解爲多個自治服務。當須要管理數據一致性時,事務可能須要在不少微服務裏執行持久化。另外一個挑戰是從多個數據庫裏查詢數據。在單體應用裏,能夠從單個數據庫輕鬆地執行inner join查詢。由於單體數據庫在分解功能性組件時改爲了多個數據庫,那麼就沒法執行inner join,而必須從多個數據庫獲取數據。這時沒有任何中央化的數據庫。
DDD Aggregate和Bounded Context是微服務的基礎構建塊,可是爲構建分佈式系統解決實際微服務挑戰而選擇具體架構時,DDD Aggregate上的事件驅動的交互系統是一種比較好的方案。這裏,我強烈推薦使用Event Sourcing,是事件爲中心的架構,經過組合各類事件來構成應用程序的狀態。Event Sourcing處理不可變事件日誌的事件存儲,每條日誌(某個對象的一次狀態變動)表明一種應用程序的狀態。由於應用程序裏的每次狀態變動都做爲不可變日誌來處理,你能夠輕鬆地排查出應用程序的故障,也能夠回到特定時間特定版本的應用程序狀態。事件存儲像版本控制系統同樣。在微服務的架構裏,咱們能夠將aggregate持久化成事件序列。事件即事實,表明系統裏發生的一些操做。這些是不可變的,不會變動或者回退。若是想要在系統裏作變動,須要往事件存儲裏寫入新的日誌來表示另外一個事件集。事件的示例包括OrderCreated,OrderApproved, OrderShipped, OrderDelivered等等。在Event Sourcing架構裏,當你從某個微服務發佈一個事件時,其餘的微服務能夠響應這些事件,而且發佈另外的事件集。有時候,事件序列相似於Unix pipe。微服務系統裏的單個事務可能會延展到多個微服務裏,能夠經過構建交互式的微服務來將事務做爲事件序列來執行。一個aggregate的每次狀態變動都是一個事件,這是系統相關的不可變的事實。爲了發佈事件讓其餘微服務知道系統裏發生的事情,可使用消息系統,好比Apcera NATS,Kafka,RabbitMQ等等。我我的喜歡的選擇是Apcera NATS和Google的Cloud Pub/Sub。事件驅動,交互式的架構是構建大規模可擴展微服務的很好的架構方案。
當使用Event Sourcing將事件序列持久化時,你可能須要一種架構方案來作微服務的查詢。架構模式,Command Query Responsibility Segregation(CQRS)是實現微服務查詢的理想模式。顧名思義,CQRS將應用程序分爲兩部分:Command來執行操做變動aggregate的狀態,Query爲aggregate的視圖提供查詢模型。咱們還可使用不一樣的數據庫來作寫操做和查詢操做。這也讓你可以經過將非規則數據裝載進讀模型的數據倉庫來提供高性能的查詢模型。NoSQL/NewSQL數據庫是很好的讀模型數據的存儲方案。
雖然Event Sourcing和CQRS,是使用微服務架構實現分佈式系統的很好的模式,可是它並不是銀彈,也有其自身的限制。你可能須要爲一些類型的微服務系統的構建使用不一樣的架構風格。可是總的來講,我認爲Event Sourcing,和CQRS的組合,是實現微服務系統的很好的方案。
在微服務架構裏,可能須要進行不少微服務間的進程間通訊。在微服務間進行進程間通訊的兩種方案以下:
經過使用帶消息系統的Event Sourcing架構,你能夠實現一種異步的事件驅動的架構來管理aggregate的狀態。你還可能須要建立API以供微服務間通訊。當你用API執行微服務間的進程間通訊時,性能和可擴展性是很是重要的。應該經過構建高性能的API,從而讓你們感受不到網絡上正在發生不少通訊。當構建大規模可擴展的系統時,基於JSON的RESTful API不是很好的選擇,由於性能挑戰會很大,而且缺乏暴露領域特定的操做爲API的能力,由於RESTful系統是基於資源的概念的。這裏,gRPC,一種高性能,開源的遠程過程調用(RPC)框架,能夠用來爲微服務間的進程間通訊構建大規模可擴展的API。默認來講,gRPC使用Protocol Buffer做爲接口定義語言(IDL),而且做爲底層消息交換格式。gRPC是Google的內部框架,Stubby的開源版本,它用來擴展支撐每秒100億次的API調用。gRPC是微服務架構裏基於API的進程間通訊的協議。
正如本文一開始所說,對於微服務有不少誤解,來自於多個開發者社區。我曾經收到過來自不一樣客戶的要求舉辦微服務workshop的請求,不少時候,客戶會提出課程大綱,這很是讓人吃驚,由於大綱上沒有任何關於微服務的東西。不少開發者社區將微服務和一些框架和工具綁定在一塊兒。不少Java開發人員堅信使用Spring Boot構建RESTful API而且利用Netflix OSS的一些工具就是微服務,而另外一些來自.NET社區的人認爲使用Azure Service Fabric運行的應用程序是微服務。也有人問我RESTful服務和微服務的區別,由於不少人認爲構建一些輕量的RESTful API就是微服務。另一些人認爲使用Spring Boot構建API是微服務。我也不知道從哪裏開始Spring Boot被誤解爲微服務的。
我感受到你們只是聽到了微服務這個詞,而且將它和一些工具以及框架聯繫在一塊兒,並無理解這種變革性架構的真正精神和意圖。這樣的狀況和架構模式,好比SOA以及工程實踐,好比Agile非常相似。我知道不少公司聲稱本身遵守敏捷工程實踐,僅僅由於他們使用了Scrum流程,而其實他們仍然以很是傳統的方式構建應用程序。TDD也是同樣,不少企業在編寫生產代碼以後才寫單元測試,而後嘗試獲得想要達到的測試覆蓋率,就認爲本身在使用TDD開發應用程序。即便是一個小衆社區,可是不少人在引入技術,模式和實踐的時候,僅僅是爲了聲稱使用了這些東西而已。
微服務的確是構建大規模可擴展應用程序的偉大的架構風格。微服務還適合構建互聯網規模的應用程序,好比Netflix,Uber,Amazon,eBay等等。可是它不是全部人都適合使用的,也並不是銀彈。雖然微服務是構建大規模可擴展應用程序,包括面向大衆的互聯網級別的應用程序的正確的架構方案,可是對於大多數其餘類型的應用程序,特別是構建企業級應用程序(有複雜的領域模型)來講,它多是錯誤的選擇。我我的不推薦用微服務來作複雜的業務應用,由於這些應用有很是複雜的領域模型。可是微服務是領域模型沒那麼複雜的,大規模可擴展的,而且可擴展是最具挑戰因素,也是成功要素的應用程序的理想選擇。對於一些類型的應用程序,微服務架構風格的實現可能會帶來不少性能問題,而且增長了系統的複雜度,最終可能致使失敗。僅僅由於和熱門技術沾邊就使用微服務可能會給你的系統帶來不少反作用。
在個人諮詢經驗裏,我認爲在絕大多數用例裏,不須要使用微服務架構,適合大多數應用程序的更好的方案是折中方案。你可使用混合方案來解決問題。你的企業可能並無Google,Amazon,Netflix,Uber,eBay,Square等公司這樣的技術能力。在你的公司裏你的問題是獨特的。架構方案必需要可以解決問題,而且使用它解決你本身的獨特問題,而不是爲了用而用。
你能夠按照以下方式改進已有的單體應用程序:將單體應用程序分解爲多個系統,而不是盲目遵照微服務的概要,選擇使用混合架構方案,使用DevOps文化以及現代化的CI/CD pipeline。微服務的最大優點是模塊化。當構建新的應用程序時,能夠經過應用模塊化系統設計原則,而不是微服務架構,來架構系統。好比,Go編程語言的打包生態系統讓你可以使用更好的模塊化思路來設計應用程序。若是以後你想要遷移到微服務來獨立擴展模塊和團隊的話,該方案還讓你能更容易地遷移到微服務上。最好是從使用模塊化系統設計原則實現單體應用開始,而後當系統和團隊發展時,能夠在確實須要的時候轉向微服務架構。
要記住你的公司和產品是獨一無二的。不要成爲技術,模式和實踐的盲目追隨者,使用折中方案解決本身的問題。爲了使用技術而使用是沒有任何意義的。
原文連接:Microservices: Overview, Misinterpretations and Misuses(翻譯:崔婧雯)===========================譯者介紹崔婧雯,現就任於IBM,高級軟件工程師,負責IBM WebSphere業務流程管理軟件的系統測試工做。曾就任於VMware從事桌面虛擬化產品的質量保證工做。對虛擬化,中間件技術,業務流程管理有濃厚的興趣。