微服務概念解析(上)

探討這一全新架構術語的確切定義

「微服務架構」概念的提出已經有很長一段時間了,但在最近幾年卻開始頻繁地出現。微服務架構是一種特定的軟件應用程序設計方式——將大型軟件拆分爲多個獨立可部署服務組合而成的套件方案。雖然這種架構風格的確切定義還存在爭議,但並不妨礙其在衆多企業的實際應用中被實踐,並體現出了具有通用特徵的業務功能、自動化部署、端點智能化以及對語言與數據的離散化控制能力。數據庫

Docker 做爲一種開源的應用容器引擎,幫助開發者將他們的應用以及依賴打包到一個可移植的容器中,便於應用的部署和擴展。而隨之產生的微容器概念和微服務正好相輔相成,經過 Docker 封裝的應用能夠輕鬆運行在以擴容能力見長的雲計算平臺上。數人云做爲專業的數據中心管理系統,提供了基於 Mesos 和 Docker 技術的企業級容器雲生產環境,經過一鍵部署、橫向擴展、持續集成等特性,助力微服務架構在企業應用環境的實踐。編程

因爲篇幅問題,本文將分上下兩篇,下篇將於明天放送給你們。後端

「微服務」——目前可謂早已人滿爲患的軟件架構領域的新興名詞。雖然咱們對於這種新生事物每每帶着一種先入爲主的蔑視與忽略態度,但通過幾年的歷練,咱們發現這種軟件構建風格正變得愈來愈具備吸引力。過去幾年中已經有諸多企業將其引入實際項目,而至今其結果仍然至關積極,這甚至促使不少同業人士開始將微服務架構做爲企業級應用程序的默認開發途徑。但遺憾的是,目前仍然缺少一套系統的概念定義,告訴咱們微服務究竟是如何實現這些成效的。數組

簡而言之,微服務架構風格[1]是一類將單一應用程序做爲由衆多小型服務構成之套件加以開發的方式,其中各項服務都擁有本身的進程並利用輕量化機制(一般爲HTTP源API)實現通訊。這些服務圍繞業務功能創建而成,且憑藉自動化部署機制實現獨立部署。這些服務匹配一套最低限度的中央式管理機制,且各服務可經過不一樣編程語言編寫而成並使用不一樣的數據存儲技術。
圖片描述
要解釋微服務風格,那麼首先應當將其與總體風格進行比較:總體應用程序做爲單一單元進行構建。企業級應用程序一般包含三個組成部分:一套客戶端用戶界面(由運行在用戶設備上的瀏覽器中的HTML頁面以及JavaScript代碼構成)、一套後端數據庫(將大量插入至數據庫管理系統的大量表構成,一般採用關係數據庫)以及一款服務器端應用程序。該服務器端應用程序將負責處理HTTP請求、執行域邏輯、對來自數據庫的數據進行檢索與更新,同時選定HTML視圖並將其發送至瀏覽器端。此服務器端應用程序一般爲單一的邏輯可執行文件[2]。任何針對該系統的變動都須要對該服務器端應用程序進行新版本構建與部署。瀏覽器

這樣的總體服務器機制在構建此類系統中可謂不可或缺。咱們用於處理請求的所有邏輯都運行在單一進程當中,容許你們使用語言中的基本功能以將該應用程序拆分爲類、函數以及命名空間。經過這種方式,咱們可以在開發人員的筆記本設備上運行並測試應用程序,同時利用一整套部署流程以確保所有變動都通過妥善測試然後被部署在生產環境當中。你們能夠將大量實例運行在一套負載均衡方案以後,從而實現橫向擴展能力。緩存

這類總體應用程序固然可以切實起效,但人們卻逐漸發現其中存在着諸多弊端——特別是在將大量應用程序部署在雲環境當中的狀況下。因爲變動週期被大量集中於一處——即便僅僅指向應用程序中的一小部分,單一變動亦要求咱們對應用程序總體進行重構與從新部署。隨着時間推移,咱們每每很難保證理想的模塊化結構,這意味着本應隻影響單一模塊的變動每每會擴散至該模塊以外。規模伸縮亦要求咱們對總體應用程序進行規模調整,而非單純爲其中必要的部分進行資源擴容。服務器

圖片描述
圖一:總體型應用程序與微服務架構應用程序架構

正是這些弊端造就了現在的微服務架構風格:即以服務套件的形式構建應用程序。除了各服務可以單獨進行部署與規模伸縮以外,每項服務還具有牢固的模塊邊界,甚至容許咱們在不一樣的服務當中使用不一樣的編程語言進行代碼編寫。另外,各服務亦可由不一樣團隊負責管理。負載均衡

咱們認爲微服務風格並不算什麼新鮮事物或者創新成果,其歷史至少能夠追溯至Unix設計時代。但咱們同時亦堅信,微服務架構一直未能受到足夠的重視,而其確實可以幫助你們更好地完成軟件開發工做。運維

微服務架構之特性

咱們沒法給微服務架構風格出具一條確切的定義,但咱們卻能夠根據該架構表現出的各種共同特性對其加以描述。正如各種根據共同特性作出的定義同樣,並非全部微服務架構都符合這些特性,但能夠確定的是具有這些特性的微服務架構佔據大部分比例。儘管咱們各部份內容的做者僅僅是相關技術社區中的活躍成員,但製做這份文檔是爲了對採用微服務架構的工做流程及成果作出總結,並且其中仍有至關一部分表述並不是嚴格定義——只應做爲常見狀況考量。

經過服務實現組件化

長久以來,咱們一直參與軟件行業以內並意識到人們對利用組件整合方式構建系統的渴望——這種思路與咱們在物理世界中採起的構建機制很是類似。而在過去幾十年當中,咱們發現已經有大量公共庫滲透到多數語言平臺當中併成爲其堅實的組成部分。

在談到咱們所使用的組件時,你們可能會發現不一樣羣體對組件的定義也有所區別。咱們對組件作出的定義是,其屬於軟件中的一類單元,且具有可更替性與可升級性。

微服務架構會使用這些庫,但其實現組件化的主要手段則是將軟件拆分紅多個服務。咱們將「庫」定義爲與程序相對接且可經過內存內函數調用發揮做用的組件,而「服務」則爲進程以外的組件,其可經過Web服務請求或者遠程程序調用等方式實現通訊。(這裏的服務概念與多數OO程序中的服務對象概念有所區別[3])。

將服務做爲組件加以使用(而非庫)的一大緣由在於,服務具有獨立可部署能力。若是你們的應用程序[4]由單一進程中的多個庫構成,那麼指向任何單一組件的變動都會導致該應用程序必須進行從新部署。但若是該應用程序被拆分紅多項服務,那麼單一服務變動將只會導致該服務進行從新部署。雖然這並不是絕對,例如某些變動會致使服務接口受到影響,但一套優秀的微服務架構旨在儘量少地對服務協議中的服務邊界及演進機制產生干擾。

將服務做爲組件的另外一個理由在於實現更爲明確的組件接口。大多數編程語言並不具有用於定義明確發佈接口的良好機制。通常來說,其只會提供說明文檔及規則以防止用戶打破組件封裝,但這同時亦會致使不一樣組件之間的耦合程度太高。利用明確的遠程調用機制,服務可以輕鬆避免此類難題。

但以這種方式使用服務亦存在必定弊端。遠程調用在資源需求方面每每遠高於進程內調用,所以遠程API須要採起粗粒度設計,但這亦會增長API的使用難度。若是你們須要更改不一樣組件間的職能分配,那麼這類需求在跨越進程邊界時每每不易實現。

經過粗略觀察,咱們每每會發現這些服務會與各運行時進程相映射——但這僅僅只是第一印象。一項服務可能由多個進程構成,且各進程始終共同進行開發與部署——這方面實例包括只由單一服務所使用的應用程序進程以及數據庫。

圍繞業務功能構建組織

當着眼於將單一大型應用程序拆分紅多個組成部分時,管理人員一般更重視技術層,其中具體包括UI團隊、服務器端邏輯團隊以及數據庫團隊。當這些團隊據此進行拆分時,即便是最簡單的變動也將給項目形成跨團隊協做負擔,並所以致使時間與預算的雙重支出。睿智的團隊會對此進行優化,同時採起兩害相權取其輕的辦法——即強制要求邏輯存在於一切與之相對接的應用程序當中。換言之,也就是實現邏輯的廣泛存在性。這正是所謂康威法則[5]的一種實際表現形式。

任何組織在設計一套系統(廣義層面的系統)時,其設計成果都會直接體現該組織所使用的溝通結構。
--梅爾文·康威,1967年
圖片描述

圖二:康威定律的實際體現

微服務方案對於各部門而言是一種不一樣於以往,且以業務功能爲核心的服務拆分及組織途徑。此類服務採用軟件方案在業務層面中的普遍實現堆棧,具體包括用戶界面、持久性存儲以及任何外部協做機制。所以,各團隊將擁有跨職能特性,包括開發過程中要求的所有技能組合:用戶體驗、數據庫以及項目管理等等。

圖片描述
圖三:由團隊邊界決定的服務邊界

微服務架構有多「微」?

儘管「微服務」早已成爲一種極具人氣的架構類型,但這一名稱卻並不能準確反映服務的實際規模——換言之,「微」服務並不必定微。在與衆多微服務從業者的交流當中,咱們發現服務的具體規模可謂多種多樣。其中規模最大的成果源自Amazon公司旗下的「兩塊披薩」團隊(即整個團隊只需兩塊披薩便可填飽肚子),這意味着其總人數在十位左右。而規模較小的團隊則由六人組成,負責支持六項服務。

那麼這就帶來了新的問題:這種十二人對單項服務的機制同一人對單項服務之間存在着怎樣的差異?兩者也許不可一律而論。就目前而言,咱們姑且認爲雙方屬於同類團隊結構,但隨着對微服務認識的持續深刻,也許咱們將來將抱持新的觀點。

採起此類組織方式的企業實例可參見www.comparethemarket.com,其各職能團隊共同負責構建並運營每款產品,而每款產品則被拆分爲一系列獨立的服務——且各服務間經過一套消息收發總線實現通訊。

大型總體應用程序亦能夠始終圍繞業務功能實際模塊化,不過這種情況並不常見。誠然,咱們都據說過由大型團隊構建的單一總體應用程序根據自身業務線進行設計與劃分。然而在這類狀況下,最大的問題在於總體應用程序在組織當中須要考慮太多背景信息。若是其總體範疇當中包含太多模塊邊界,那麼團隊中的單一成員將很難經過短時間記憶對其進行管理。除此以外,咱們發現這種模塊化業務線的維護工做還要求相關人員具有極高的專業技能水平。相比之下,服務組件可以令拆分方式更爲明確,從而大大簡化團隊邊界的設定與認知。

產品而非項目

大部分應用程序開發工做都會遵循項目模式:其目標在於交付軟件方案中的特定部分,並擁有直觀的完成指標。在軟件開發工做完成後,其會被傳遞至運維部門,這時負責構建該軟件的團隊也將即刻解散。

微服務的支持者們則認爲這種模式並不可取——他們的主張是相關團隊應該伴隨產品走過整個生命週期。這方面最典型的例子應該是Amazon公司提出的「誰構建,誰運行」原則,其中開發團隊須要對生產環境下的軟件成果承擔所有責任。這就要求開發人員在平常工做中全程關注其軟件的生產運行狀況,同時掌握來自用戶的反饋意見,意味着他們須要在必定程度上爲用戶提供技術支持服務。

產品的定位應始終與業務功能相協調。相較於以往將軟件視爲一整套已經完成的功能集的心態,微服務架構要求咱們全程與之保持關聯,並思考該軟件可以如何協助用戶增強業務功能。

固然,咱們徹底能夠將一樣的思路引入總體應用程序當中,不過大量小型服務集合可以顯著簡化服務開發人員與及用戶之間的我的聯繫。

智能化端點與傻瓜式流程

在跨越不一樣進程構建通訊結構時,咱們發現不少產品及方案會直接把智能化機制塞進通訊機制本體當中。這方面的典型實例就是企業服務總線(簡稱ESB),ESB產品當中一般包含複雜度極高的消息跌幅、編排、轉換以及業務規則應用等機制。

微服務社區則傾向於使用另外一種實現方式:智能化端點與傻瓜式流程。採用微服務架構的應用程序旨在儘量實現解耦化與關聯性——它們各自擁有本身的域邏輯,並且在經典Unix場景下的運做方式更像是過濾器機制——接收請求、應用合適的邏輯並生成響應。這一切都經過簡單的REST類協議實現編排,而非經由WS-Choreography或者BPEL等複雜協議以及中央編排工具實現。

目前最經常使用的兩類協議爲配合源API的HTTP請求-響應與輕量化消息收發協議[6]。對於前者,最簡練而準確的說明是:

立足於Web,而非居於Web背後。
-- Ian Robinson**

微服務團隊採用的正是萬維網(在很大程度上亦包括Unix在內)所遵循的原則與協議。通常來說,其使用的資源可以爲開發人員或者運維人員輕鬆實現緩存處理。

第二類做法則是立足於輕量化消息總線實現消息收發。這類基礎設施選項一般具有傻瓜式特性(這種傻瓜特性體如今實現操做上,即只需匹配消息路由機制,再無其它)——以RabbitMQ或者ZeroMQ爲表明的簡單實現方案僅僅須要提供一套可靠的異步結構,而服務的所有智能化元素仍然存在於端點當中並負責消息的生成與消費。

在總體應用程序當中,各組件在進程內執行並經過方法調用或者函數調用的方式實現彼此通訊。將總體應用程序轉化爲微服務形式的最大難題在於改變這種通訊模式。由內存內方法調用指向PC通訊機制的簡單轉換每每沒法良好起效。相反,你們須要利用粗粒度方式取代本來的細粒度通訊機制。

腳註

1: 「微服務」一詞最先被威尼斯附近的一個軟件架構師小組於2011年5月首次說起,當時他們用這個詞彙來描述本身近期研究項目當中所涉及的通用性架構機制。2012年5月,該小組做出最終決議,認爲「微服務」是最適合的架構名稱。2012年3月,James在《微服務-Java以及Unix方式》當中就此發表了一篇案例研究報告,而Fred George也幾乎在同一時間進行了相同的工做。Netflix公司的Adrian Cockcroft將微服務架構稱爲「細化SOA」,並認爲這是一套在Web規模下具有開創意義的架構類型。Joe Walnes、Dan North、Evan Botcher以及Graham Tackley也分別在這篇文章中對此做出了評論。

2: 文章中所使用的「總體」一詞長久以來一直被Unix業界所使用。其首次出如今《Unix編程藝術》一書中,用於描述那些過於龐大的系統方案。

3: 不少面向對象設計人員,也包括咱們本身,都會在域驅動設計當中使用「服務對象」這一表述,專指那些並不具有實質性聯繫但卻擁有重要做用的對象。這與咱們在本文中所使用的「服務」一詞在表意上徹底不一樣。遺憾的是,服務這個詞彙同時具有兩種含義,而咱們對這種多義詞也沒有更好的處理辦法。

4: 咱們將一款應用程序視爲一套社會性體系,其中融合了代碼庫、函數組以及供應主體。

5: 你們能夠查看梅爾文 康韋網站上的原文論述。

6: 對於規模極爲龐大的應用體系,企業一般會採用二進制協議——例如protobufs。使用二進制協議的系統仍然符合智能化端點與傻瓜式通道的特性——併爲了規模化而在透明度方面做出妥協。不過大多數Web方案與絕大多數企業不須要在這方面考慮太多——通常來說,透明度越高、效果就越好。

相關文章
相關標籤/搜索