引言:“微服務(wù)”是當(dāng)前軟件架構(gòu)領(lǐng)域非常熱門的詞匯,能找到很多關(guān)于微服務(wù)的定義、準(zhǔn)則,以及如何從微服務(wù)中獲益的文章,在企業(yè)的實(shí)踐中去應(yīng)用“微服務(wù)”的資源卻很少。本篇文章中,會(huì)介紹微服務(wù)架構(gòu)(Microservices Architecture)的基礎(chǔ)概念,以及如何在實(shí)踐中具體應(yīng)用。
單體架構(gòu)(Monolithic Architecture )
企業(yè)級(jí)的應(yīng)用一般都會(huì)面臨各種各樣的業(yè)務(wù)需求,而常見的方式是把大量功能堆積到同一個(gè)單體架構(gòu)中去。比如:常見的
ERP、CRM等系統(tǒng)都以單體架構(gòu)的方式運(yùn)行,同時(shí)由于提供了大量的業(yè)務(wù)功能,隨著功能的升級(jí),整個(gè)研發(fā)、發(fā)布、定位問題,擴(kuò)展,升級(jí)這樣一個(gè)“怪物”系統(tǒng)會(huì)變得越來越困難。
單體架構(gòu)的初期效率很高,應(yīng)用會(huì)隨著時(shí)間推移逐漸變大。在每次的迭代中,開發(fā)團(tuán)隊(duì)都會(huì)面對(duì)新功能,然后開發(fā)許多新代碼,隨著時(shí)間推移,這個(gè)簡(jiǎn)單的應(yīng)用會(huì)變成了一個(gè)巨大的怪物。
圖1 單體架構(gòu)
大部分企業(yè)通過SOA來解決上述問題,SOA的思路是把應(yīng)用中相近的功能聚合到一起,以服務(wù)的形式提供出去。因此基于SOA架構(gòu)的應(yīng)用可以理解為一批服務(wù)的組合。SOA帶來的問題是,引入了大量的服務(wù)、消息格式定義和規(guī)范。
多數(shù)情況下,SOA的服務(wù)直接相互獨(dú)立,但是部署在同一個(gè)運(yùn)行環(huán)境中(類似于一個(gè)Tomcat實(shí)例下,運(yùn)行了很多web應(yīng)用)。和單體架構(gòu)類似,隨著業(yè)務(wù)功能的增多SOA的服務(wù)會(huì)變得越來越復(fù)雜,本質(zhì)上看沒有因?yàn)槭褂肧OA而變的更好。圖1,是一個(gè)包含多種服務(wù)的在線零售網(wǎng)站,所有的服務(wù)部署在一個(gè)運(yùn)行環(huán)境中,是一個(gè)典型的單體架構(gòu)。
單體架構(gòu)的應(yīng)用一般有以下特點(diǎn):
-
設(shè)計(jì)、開發(fā)、部署為一個(gè)單獨(dú)的單元。
-
會(huì)變得越來越復(fù)雜,最后導(dǎo)致維護(hù)、升級(jí)、新增功能變得異常困難
-
很難以敏捷研發(fā)模式進(jìn)行開發(fā)和發(fā)布
-
部分更新,都需要重新部署整個(gè)應(yīng)用
-
水平擴(kuò)展:必須以應(yīng)用為單位進(jìn)行擴(kuò)展,在資源需求有沖突時(shí)擴(kuò)展變得比較困難(部分服務(wù)需要更多的計(jì)算資源,部分需要更多內(nèi)存資源)
-
可用性:一個(gè)服務(wù)的不穩(wěn)定會(huì)導(dǎo)致整個(gè)應(yīng)用出問題
-
創(chuàng)新困難:很難引入新的技術(shù)和框架,所有的功能都構(gòu)建在同質(zhì)的框架之上
微服務(wù)架構(gòu)(Microservices Architecture)
微服務(wù)架構(gòu)的核心思想是,一個(gè)應(yīng)用是由多個(gè)小的、相互獨(dú)立的、微服務(wù)組成,這些服務(wù)運(yùn)行在自己的進(jìn)程中,開發(fā)和發(fā)布都沒有依賴。
多數(shù)人對(duì)于微服務(wù)的定義是,把本來運(yùn)行在單體架構(gòu)中的服務(wù)拆分成相互獨(dú)立的服務(wù),并運(yùn)行在各自的進(jìn)程中。在我看來,不僅如此。最關(guān)鍵的地方在于,不同的服務(wù)能依據(jù)不同的業(yè)務(wù)需求,構(gòu)建的不同的技術(shù)架構(gòu)之上,并且聚焦在有限的業(yè)務(wù)功能之上。
因此,在線零售網(wǎng)站可以用圖2的微服務(wù)架構(gòu)來簡(jiǎn)單概括。基于業(yè)務(wù)需求,需要增加一個(gè)賬戶服務(wù)微服務(wù),因此構(gòu)建微服務(wù)絕不是在單體架構(gòu)中把服務(wù)拆分開這么簡(jiǎn)單。
圖2 微服務(wù)架構(gòu)
微服務(wù)設(shè)計(jì):規(guī)模、范圍、業(yè)務(wù)功能
你可能從零開始用微服務(wù)來構(gòu)建應(yīng)用,也可能重構(gòu)現(xiàn)有系統(tǒng),確定微服務(wù)的規(guī)模,范圍和功能都特別重要。讓我們討論一些有關(guān)微服務(wù)設(shè)計(jì)的關(guān)鍵問題和對(duì)它的誤解:
“微”很容易被誤解:很多開發(fā)者會(huì)傾向于把服務(wù)往盡量小的顆粒度去做
在SOA方式下,服務(wù)都還是以單體架構(gòu)在運(yùn)行,用于支持不同的功能。如果依舊采用SAO類似的服務(wù),僅僅是名義上叫做微服務(wù),并不能帶來任何微服務(wù)的優(yōu)勢(shì)。
那我們?cè)谖⒎⻊?wù)中應(yīng)該怎樣設(shè)計(jì)呢。以下是微服務(wù)的設(shè)計(jì)指南:
-
職責(zé)單一原則(Single ResponsibilityPrinciple):把某一個(gè)微服務(wù)的功能聚焦在特定業(yè)務(wù)或者有限的范圍內(nèi)會(huì)有助于敏捷開發(fā)和服務(wù)的發(fā)布。
-
設(shè)計(jì)階段就需要把業(yè)務(wù)范圍進(jìn)行界定。
-
需要關(guān)心微服務(wù)的業(yè)務(wù)范圍,而不是服務(wù)的數(shù)量和規(guī)模盡量小。數(shù)量和規(guī)模需要依照業(yè)務(wù)功能而定。
-
于SOA不同,某個(gè)微服務(wù)的功能、操作和消息協(xié)議盡量簡(jiǎn)單。
-
項(xiàng)目初期把服務(wù)的范圍制定相對(duì)寬泛,隨著深入,進(jìn)一步重構(gòu)服務(wù),細(xì)分微服務(wù)是個(gè)很好的做法。
微服務(wù)消息
在單體架構(gòu)中,不同功能之間通信通過方法調(diào)用,或者跨語言通信。SOA降低了這種語言直接的耦合度,采用基于SOAP協(xié)議的web服務(wù)。這種web服務(wù)的功能和消息體定義都十分復(fù)雜,微服務(wù)需要更輕量的機(jī)制。
同步消息 – REST, Thrift
同步消息就是客戶端需要保持等待,直到服務(wù)器返回應(yīng)答。REST是微服務(wù)中默認(rèn)的同步消息方式,它提供了基于HTTP協(xié)議和資源API風(fēng)格的簡(jiǎn)單消息格式,多數(shù)微服務(wù)都采用這種方式(每個(gè)功能代表了一個(gè)資源和對(duì)應(yīng)的操作)。
Thrift是另外一個(gè)可選的方案。它采用接口描述語言定義并創(chuàng)建服務(wù),支持可擴(kuò)展的跨語言服務(wù)開發(fā),所包含的代碼生成引擎可以在多種語言中,如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 等創(chuàng)建高效的、無縫的服務(wù),其傳輸數(shù)據(jù)采用二進(jìn)制格式,相對(duì) XML 和 JSON 體積更小,對(duì)于高并發(fā)、大數(shù)據(jù)量和多語言的環(huán)境更有優(yōu)勢(shì)。
圖3 REST接口,對(duì)外微服務(wù)
異步消息 – AMQP, STOMP, MQTT
異步消息就是客戶端不需要一直等待服務(wù)應(yīng)答,有應(yīng)到后會(huì)得到通知。某些微服務(wù)需要用到異步消息,一般采用AMQP, STOMP, MQTT。
消息格式 – JSON, XML, Thrift, ProtoBuf, Avro
消息格式是微服務(wù)中另外一個(gè)很重要的因素。SOA的web服務(wù)一般采用文本消息,基于復(fù)雜的消息格式(SOAP)和消息定義(xsd)。微服務(wù)采用簡(jiǎn)單的文本協(xié)議JSON和XML,基于HTTP的資源API風(fēng)格。如果需要二進(jìn)制,通過用到Thrift, ProtoBuf, Avro。
服務(wù)約定 – 定義接口 – Swagger, RAML, Thrift IDL
如果把功能實(shí)現(xiàn)為服務(wù),并發(fā)布,需要定義一套約定。單體架構(gòu)中,SOA采用WSDL,WSDL過于復(fù)雜并且和SOAP緊耦合,不適合微服務(wù)。
REST設(shè)計(jì)的微服務(wù),通常采用Swagger和RAML定義約定。
對(duì)于不是基于REST設(shè)計(jì)的微服務(wù),比如Thrift,通常采用IDL(Interface Definition Languages),比如Thrift IDL。
微服務(wù)集成 (服務(wù)間通信)
微服務(wù)架構(gòu)下,應(yīng)用的服務(wù)直接相互獨(dú)立。在一個(gè)具體的商業(yè)應(yīng)用中,需要有些機(jī)制支持微服務(wù)之間通信。因此服務(wù)間的通信機(jī)制特別重要。
SOA體系下,服務(wù)之間通過企業(yè)服務(wù)總線(Ent
ERPrise Service Bus)通信,許多業(yè)務(wù)邏輯在中間層(消息的路由、轉(zhuǎn)換和組織)。微服務(wù)架構(gòu)傾向于降低中心消息總線(類似于ESB)的依賴,將業(yè)務(wù)邏輯分布在每個(gè)具體的服務(wù)終端。
大部分微服務(wù)基于HTTP、JSON這樣的標(biāo)準(zhǔn)協(xié)議,集成不同標(biāo)準(zhǔn)和格式變的不再重要。另外一個(gè)選擇是采用輕量級(jí)的消息總線或者網(wǎng)關(guān),有路由功能,沒有復(fù)雜的業(yè)務(wù)邏輯。下面就介紹幾種常見的架構(gòu)方式。
點(diǎn)對(duì)點(diǎn)方式 – 直接調(diào)用服務(wù)
點(diǎn)對(duì)點(diǎn)方式中,服務(wù)之間直接用。每個(gè)微服務(wù)都開放REST API,并且調(diào)用其它微服務(wù)的接口。
圖4 通過點(diǎn)對(duì)點(diǎn)方式通信
很明顯,在比較簡(jiǎn)單的微服務(wù)應(yīng)用場(chǎng)景下,這種方式還可行,隨著應(yīng)用復(fù)雜度的提升,會(huì)變得越來越不可維護(hù)。這點(diǎn)有些類似SOA的ESB,盡量不采用點(diǎn)對(duì)點(diǎn)的集成方式。
點(diǎn)對(duì)點(diǎn)有下面幾個(gè)缺點(diǎn):
-
非功能的需求,比如用戶授權(quán)、限制、監(jiān)控,需要在每個(gè)微服務(wù)中進(jìn)行實(shí)現(xiàn)
-
隨著功能的演進(jìn),服務(wù)會(huì)變得越來越復(fù)雜。
-
不同的服務(wù)直接,客戶端和服務(wù)直接沒有控制功能(監(jiān)控、跟蹤、過濾)
-
直接通信在大型系統(tǒng)設(shè)計(jì)中,一般是反面典型。
因此,如果設(shè)計(jì)一個(gè)大型的微服務(wù)系統(tǒng),盡量避免點(diǎn)對(duì)點(diǎn)的通信方式,也不能像ESB這樣重量級(jí)的總線。而是一個(gè)輕量級(jí)的總線,能夠提供非業(yè)務(wù)功能的抽象。這就是API網(wǎng)關(guān)方式。
API-網(wǎng)關(guān)方式
API網(wǎng)關(guān)方式的核心要點(diǎn)是,所有的客戶端和消費(fèi)端都通過統(tǒng)一的網(wǎng)關(guān)接入微服務(wù),在網(wǎng)關(guān)層處理所有的非業(yè)務(wù)功能個(gè)。通常,網(wǎng)關(guān)也是提供REST/HTTP的訪問API。服務(wù)端通過API-GW注冊(cè)和管理服務(wù)。
圖5 通過API-網(wǎng)關(guān)暴露微服務(wù)
用我們網(wǎng)上商店的例子,在圖5中,所有的業(yè)務(wù)接口通過API網(wǎng)關(guān)暴露,是所有客戶端接口的唯一入口。微服務(wù)之間的通信也通過API網(wǎng)關(guān)。
采用網(wǎng)關(guān)方式有如下優(yōu)勢(shì):
-
有能力為微服務(wù)接口提供網(wǎng)關(guān)層次的抽象。比如:微服務(wù)的接口可以各種各樣,在網(wǎng)關(guān)層,可以對(duì)外暴露統(tǒng)一的規(guī)范接口。
-
統(tǒng)一控制安全、監(jiān)控、限流等非業(yè)務(wù)功能。
-
每個(gè)微服務(wù)會(huì)變得更加輕量,非業(yè)務(wù)功能個(gè)都在網(wǎng)關(guān)層統(tǒng)一處理,微服務(wù)只需要關(guān)注業(yè)務(wù)邏輯
目前,API網(wǎng)關(guān)方式應(yīng)該是微服務(wù)架構(gòu)中應(yīng)用最廣泛的設(shè)計(jì)模式。
消息代理方式
微服務(wù)也可以集成在異步的場(chǎng)景下,通過隊(duì)列和訂閱主題,實(shí)現(xiàn)消息的發(fā)布和訂閱。一個(gè)微服務(wù)可以是消息的發(fā)布者,把消息通過異步的方式發(fā)送到隊(duì)列或者訂閱主題下。作為消費(fèi)者的微服務(wù)可以從隊(duì)列或者主題共獲取消息。通過消息中間件把服務(wù)之間的直接調(diào)用解耦。
圖6 異步通信方式
通常異步的生產(chǎn)者/消費(fèi)者模式,通過AMQP、MQTT等異步消息規(guī)范。
數(shù)據(jù)的去中心化
單體架構(gòu)中,不同功能的服務(wù)模塊都把數(shù)據(jù)存儲(chǔ)在某個(gè)中心數(shù)據(jù)庫(kù)中。
圖7 單體架構(gòu),用一個(gè)數(shù)據(jù)庫(kù)存儲(chǔ)所有數(shù)據(jù)
微服務(wù)方式,多個(gè)服務(wù)之間的設(shè)計(jì)相互獨(dú)立,數(shù)據(jù)也應(yīng)該相互獨(dú)立(比如,某個(gè)微服務(wù)的數(shù)據(jù)庫(kù)結(jié)構(gòu)定義方式改變,可能會(huì)中斷其它服務(wù))。因此,每個(gè)微服務(wù)都應(yīng)該有自己的數(shù)據(jù)庫(kù)。
圖8 每個(gè)微服務(wù)有自己私有的數(shù)據(jù)庫(kù),其它微服務(wù)不能直接訪問
數(shù)據(jù)去中心話的核心要點(diǎn):
-
每個(gè)微服務(wù)有自己私有的數(shù)據(jù)庫(kù)持久化業(yè)務(wù)數(shù)據(jù)
-
每個(gè)微服務(wù)只能訪問自己的數(shù)據(jù)庫(kù),而不能訪問其它服務(wù)的數(shù)據(jù)庫(kù)
-
某些業(yè)務(wù)場(chǎng)景下,需要在一個(gè)事務(wù)中更新多個(gè)數(shù)據(jù)庫(kù)。這種情況也不能直接訪問其它微服務(wù)的數(shù)據(jù)庫(kù),而是通過對(duì)于微服務(wù)進(jìn)行操作。
數(shù)據(jù)的去中心化,進(jìn)一步降低了微服務(wù)之間的耦合度,不同服務(wù)可以采用不同的數(shù)據(jù)庫(kù)技術(shù)(SQL、NoSQL等)。在復(fù)雜的業(yè)務(wù)場(chǎng)景下,如果包含多個(gè)微服務(wù),通常在客戶端或者中間層(網(wǎng)關(guān))處理。
轉(zhuǎn)載請(qǐng)注明出處:拓步ERP資訊網(wǎng)http://www.ezxoed.cn/
本文標(biāo)題:微服務(wù)實(shí)戰(zhàn):從架構(gòu)到發(fā)布(一)
本文網(wǎng)址:http://www.ezxoed.cn/html/solutions/14019319971.html