微服務的鑑定與思考

微服務有且僅有一種很是專項的功能,經過遠程API來提供系統其他功能。舉個例子:試想一下倉庫的管理系統,這樣的系統中微服務可能提供的一些功能有:算法

  接收庫存數據庫

  計算新的庫存該存到什麼地方服務器

  計算在倉庫內將庫存運往正確放置點的路線架構

  爲倉庫員工分配運送路線框架

  接收訂單分佈式

  計算倉庫內指定一組訂單的揀貨路線微服務

  爲倉庫員工分配揀貨路線性能

  以上這些功能(可能還會有更多)都是由單個微服務實現的。每一個微服務都有單獨的運行線程,而且能夠獨立於其餘微服務進行部署。一樣每一個微服務都有本身的專用數據庫,儘管每一個微服務都會與其餘微服務協做與溝通。學習

  一個系統中的不一樣微服務徹底有可能在不一樣的平臺上實現,一些可能在.NET上,另一些在Erlang,其餘的在Node.js上。只要能協調多語言的問題,各個微服務彼此正常溝通,就能奏效。HTTP是良好的溝通選擇:上面全部提到的平臺,還有不少其餘平臺都能很好的處理HTTP。固然也有符合微服務溝通規則的其餘技術:例如一些隊列、一些服務總線還有一些二進制協議。在這些技術當中,HTTP多是支持最普遍的,至關容易理解,並且就像萬維網所展現的那樣很好用,整體來講是很好的方案。測試

  再次以倉庫系統爲例:該系統的一個微服務是分配揀貨路線微服務。圖一展現了「分配揀貨路線微服務」從另外一個協做微服務收到的請求:爲指定員工設定了下一次的揀貨路線。分配揀貨線路微服務必須爲員工找到合適的線路,而另外一個微服務則完成計算最優路線的工做,分配揀貨路線微服務只需收到揀貨路線通知並肯定如何爲僱員分配路線。在分配揀貨路線的微服務中,收到請求——分配指定員工的揀貨路線,搜索數據庫,找到合適的揀貨路線,並從中選擇一個返回給微服務調用。

  

 

  微服務架構是什麼?

  微服務是一種架構類型,屬於輕量級的面向服務體系架構,這些服務都是嚴格專一於執行同一件事並把它作好。

  使用微服務做爲主要架構類型的系統是一個擁有大量協調微服務的分佈式系統,每一個微服務分管本身的進程。因爲微服務之間緊密協做,每一個微服務只提供拼圖的一小塊,而系統作爲完整的做品存在。協做時,各服務彼此經過一個不綁定具體平臺的輕量級媒介進行溝通,好比.NET,Java或者Erlang。如前所述,本書中全部微服務之間的溝通都是經過HTTP的,不過還有其餘可選方案,好比隊列、總線或者相似Thrift的二進制協議。

  在構建與維護複雜的服務器端軟件系統時,微服務架構類型迅速流行起來。能夠想見,這樣一來:在傳統的面向服務方法和總體架構(monolithic architectures)中,微服務都有大量潛在好處。在運做良好的前提下,微服務在可塑性、可擴展性與彈性方面都具備優點,並容許使用者只花費很短的時間就實現從開始到生產環境部署的過程。

  微服務特性

  雖然已經說了這麼多,不過定義還很模糊。爲了縮小微服務的界定範圍,咱們先來考察一下微服務的特性。在筆者理解中,微服務這個術語的特性是:

  1. 負責單個功能

  2. 單獨部署

  3. 包含一個或多個進程

  4. 擁有本身的數據存儲

  5. 一支小團隊就能維護幾個微服務

  6. 可替換的

  這張特性列表不但幫助識別微服務,還可以在發揮微服務優點(一個擁有可塑性、可擴展性與彈性的系統)的前提下協助界定與執行該服務,依次看下去。

  負責單個功能

  微服務在整個系統中只負責單個功能。這句話分解來講包含兩部份內容:第一,微服務只有單個責任;第二,負責的是功能。單一責任原則有幾種描述,其中一個傳統的描述是:

  「當須要修改某個類的時候緣由有且只有一個("There should never be more than one reason for a class to change.")」 -- Robert C. Martin SRP: 單一責任原則

  儘管這種說法特別提到了「類」,這一原則卻不僅適用於面嚮對象語言的類層面。經過微服務,這裏在服務層面運用單一責任原則。另外一種較新的說法也是描述單一責任原則的:

  聚合因同一理由變化的東西,分離因不一樣理由而變化的東西。("Gather together the things that change for the same reasons. Separate those things that change for different reasons.")-- Robert C. Martin單一責任原則

  這一原則適用於微服務:微服務應當正好實現一個功能。微服務必須只在功能改變時纔跟着改變。此外,應當努力讓微服務徹底實現相關功能,這樣在功能改變時微服務也得跟着改變。

  微服務系統的一個功能可能意味着幾件事。首先,功能多是業務方面的。業務功能就是系統所完成的、對系統的目的有貢獻的事情——好比持續追蹤用戶的購物車或者計算價格。梳理一個系統擁有的獨立業務功能有一個好辦法,就是使用Domain Driven Design。第二,有時候功能能夠是多個其餘微服務須要利用的技術功能——例如集成到一些第三方系統中。技術功能並不是是將系統分解成微服務的主因,而是因爲微服務執行業務功能須要一樣的技術能力而致使的結果。

  獨立部署

  每一個微服務都應當是單獨部署的。也就是說:當你改變一個特定的微服務時,須要可以將微服務的變動部署到生產環境中,而無需部署或觸及系統的其餘部分。事實上,系統中的其餘微服務應當在改動的微服務部署之時,還有新版本部署完成以後繼續持續運行。

  試想一下電子商務網站:每次購物車微服務發生改變時,都應當能當即進行部署。同時價格計算微服務、推薦微服務、產品目錄微服務等等應當繼續運行並知足用戶的請求。

  可以單獨部署每一個微服務很是重要,緣由有好幾個。其中一點是,在一個微服務系統中有不少微服務,每一個微服務都會與其餘幾個相協做。各部分的開發工做同時完成,或者不少微服務並行。若是須要按同一步調部署全部或者不少微服務的話,管理部署很快就會變得捉襟見肘,特別是常常會致使高風險部署,這是咱們很但願避免的。相反咱們但願可以對每一個微服務進行小變動部署,這樣風險會更低。

  可以在系統的其餘部分繼續正常運行的時候部署單個微服務,構建過程必須牢記這一點:每一個微服務必須打包到不一樣的構件或程序包中。一樣地,部署過程自己還必須支持在其餘微服務繼續運行之時,獨立部署變動的微服務。好比,每次將微服務部署到服務器的過程當中,爲了減小停機時間可使用滾動部署的辦法。

  微服務互動的方式也受到指望獨立部署的影響。改變微服務接口必須在大多數狀況下向後兼容,這樣其餘現有的微服務就能夠繼續按照與舊版本融合的方式與新版本集成了。此外,微服務互動的方式必須有彈性,每一個微服務必須在其餘微服務偶爾出錯時繼續保持最佳運行狀態。一個微服務出錯——好比由於部署時的短暫停機——必須不影響其餘微服務運行,只是形成功能縮減或者進行時間稍長。

  包含一個或多個進程

  一個微服務由一個或多個進程組成,這個特性有兩面性。首先,每一個微服務獨立於其餘微服務運行;其次,每一個微服務能夠擁有不止一個進程。

  某微服務獨立運行,是因爲但願保持每一個微服務儘量獨立於其餘微服務繼續運行。此外,爲了獨立部署微服務,那個微服務不能按照其餘微服務的方式來運行。再用購物車微服務來舉例:若是按照與產品目錄微服務相同的方式運行,購物車代碼可能對產品目錄代碼產生負面影響,這表明着購物車微服務與產品目錄微服務之間緊密卻不受歡迎的耦合。

  

 

  如今思考一下部署購物車微服務的新版本狀況。要麼得從新部署產品目錄微服務,要麼就得有某種動態代碼加載功能,來替換正在運行中的購物車代碼。前一個選項與微服務獨立部署的原則徹底相違背,後一個選項太過複雜並且起碼有因爲部署購物車微服務而形成產品目錄微服務停機的風險。

  每一個微服務可能包含不止一個進程,表面來看可能使人驚訝,畢竟這裏嘗試讓每一個微服務儘量簡單好控制,那麼爲何要自找麻煩擁有不止一個進程呢?用電子商務網站作個比方:執行推薦算法會在電子商務網站上展現推薦選項,這些算法都在這個微服務所屬的進程中運行,還存儲了提供推薦須要的數據。這個數據可能存儲在硬盤文件裏,不過更有可能存在數據庫裏,在第二個進程中運行的數據庫也屬於這個微服務。一個微服務一般擁有2個或以上進程的需求,就是由於微服務須要實現所須要的一切,以提供包含諸如數據存儲還有後臺處理之類的功能。

  擁有本身的數據存儲

  一個微服務包含數據存儲,在該進程中存儲所需的數據,正是因爲咱們但願微服務的範圍是一個完整的功能。大多數業務功能須要一些數據存儲,例如對於產品目錄微服務來講,每一個產品的信息須要存儲下來。爲了保持產品目錄微服務與其餘微服務的鬆散耦合性,存儲的產品信息數據徹底包含在產品目錄微服務之中。由產品目錄微服務肯定什麼時候、如何存儲產品信息。其餘微服務——好比購物車微服務——只能經過產品目錄微服務的接口來訪問產品信息,而永遠不能直接訪問產品目錄存儲。

  

 

  每一個微服務包含本身的數據存儲,這開啓了根據每一個微服務需求,爲不一樣微服務使用不一樣數據庫技術的可能性。產品目錄微服務可能使用SQL服務器來存儲產品信息,而購物車微服務可能用Redis來存儲每一個用戶的購物車信息,推薦微服務則使用Elastic Search索引來提供推薦服務。爲每一個微服務所選擇的數據庫技術是執行的一部分,對其餘微服務來說是隱藏的。將數據庫技術與每一個微服務需求進行混合配對的好處在於,每一個微服務可使用最適合的數據庫。對開發時間、性能和可擴展性頗有好處,不過也帶來了成本問題。數據庫技術上很是複雜,學習使用和在生產環境上運行一個可靠的數據庫都不容易。爲微服務選擇數據庫信息時,應當考慮取捨的問題。不過也要記住,因爲微服務擁有本身的數據存儲,稍候切換到另外一個數據庫也是可行的。

  小團隊就能維護

  到如今本文並未討論太多微服務的規模問題,雖然微服務中的「微」暗示着這些服務規模很小。但這裏並不認爲討論微服務應當有幾行代碼,需求/用例有多少或者應當執行的功能點有幾個這些有什麼意義。全部這些取決於微服務所提供功能的複雜性。真正有意義的是考慮維護微服務的工做量。指出微服務規模大小的一條經驗法則是:一個5人小團隊就應當可以維護幾個或者更多的微服務。維護一個微服務包括保持其正常運行並達成目標:開發新的功能、從發展到過大規模的微服務中分解出新的微服務、監控測試與修復bug及其餘。考慮到一個小團隊應當可以完成幾個微服務的全部這些工做,你應當對典型的微服務規模有概念了。

  可替換的

  一個微服務是可替換的,表明着它能夠在合理的時間框架內從頭重寫。也就是說,維護該微服務的團隊能夠決定用全新的實現來替代現有的,而且不會打亂正常工做的進程。這條特性也是微服務規模的一條約束:若是一個微服務成長地太大,替代成本就會太高,只有保持小型才能讓重寫比較現實。

  爲何團隊會決定重寫微服務?一個緣由多是代碼太亂,另外一個緣由是微服務不能在生產環境中運行良好。儘管這些狀況並不是所願,卻出體現了微服務的優點。即使努力構建微服務,時間形成的需求變動可能促使現有的實現方式沒法知足需求而須要變動。並且隨着時間過去,代碼可能會因爲初始設計周折太多而變成一團亂麻。性能要求可能會須要大幅提高,而現有設計沒法知足。若是一個微服務小到在合理時間框架內便能重寫,偶爾出現這些狀況都是ok的。瞭解現有實現全部知識的同時,再結合新需求考慮,就能簡單地完成重寫工做。

相關文章
相關標籤/搜索