什么是微服務架構
“微服務”一詞源於Martin Fowler的名為Microservices的博文, 可以在他的官方博客 上找到: http://mar巨nfowler.com/articles/microservices.html。
簡單地說, 微服務是系統架構上的一種設計風格, 它的主旨是將一個原本獨立的系統 拆分成多個小型服務,這些小型服務都在各自獨立的進程中運行,服務之間通過基於HTTP 的RESTful API進行通信協作。 被拆分成的每一個小型服務都圍繞着系統中的某一項或一 些耦合度較高的業務功能進行構建, 並且每個服務都維護着自身的數據存儲、 業務開發、 自動化測試案例以及獨立部署機制。 由千有了輕量級的通信協作基礎, 所以這些微服務可 以使用不同的語言來編寫。
與單體系統的區別
在以往傳統的企業系統架構中, 我們針對一個復雜的業務需求通常使用對象或業務類 型來構建一個單體項目。 在項目中我們通常將需求分為三個主要部分: 數據庫、 服務端處 理、 前端展現。 在業務發展初期, 由於所有的業務邏輯在一個應用中, 開發、 測試、 部署 都還比較容易且方便。 但是, 隨着企業的發展, 系統為了應對不同的業務需求會不斷為該 單體項目增加不同的業務模塊; 同時隨着移動端設備的進步, 前端展現模塊已經不僅僅局 限於Web的形式,這對千系統后端向前端的支持需要更多的接口模塊。 單體應用由千面對 的業務需求更為寬泛, 不斷擴大的需求會使得單體應用變得越來越腕腫。 單體應用的問題就逐漸凸顯出來, 由於單體系統部署在一個進程內, 往往我們修改了一個很小的功能, 為 了部署上線會影響其他功能的運行。
並且, 單體應用中的這些功能模塊的使用場景、 並發 量、 消耗的資源類型都各有不同, 對於資源的利用又互相影響, 這樣使得我們對各個業務 模塊的系統容量很難給出較為准確的評估。 所以, 單體系統在初期雖然可以非常方便地進 行開發和使用, 但是隨着系統的發展, 維護成本會變得越來越大, 且難以控制。 為了解決單體系統變得龐大脯腫之后產生的難以維護的問題,微服務架構誕生了並被 大家所關注。 我們將系統中的不同功能模塊拆分成多個不同的服務, 這些服務都能夠獨立 部署和擴展。 由於每個服務都運行在自己的進程內, 在部署上有穩固的邊界, 這樣每個服 務的更新都不會影響其他服務的運行。 同時, 由千是獨立部署的, 我們可以更准確地為每 個服務評估性能容量, 通過配合服務間的協作流程也可以更容易地發現系統的瓶頸位置, 以及給出較為准確的系統級性能容量評估。
如何實施微服務
在實施微服務之前, 我們必須要知道, 微服務雖然有非常多吸引人的優點, 但是也因 為服務的拆分引發了諸多原本在單體應用中沒有的問題。
• 運維的新挑戰:在微服務架構中, 運維人員需要維護的進程數量會大大增加。 有條 不紊地將這些進程編排和組織起來不是一件容易的事, 傳統的運維人員往往很難適 應這樣的改變。 我們需要運維人員有更多的技能來應對這樣的挑戰, 運維過程需要 更多的自動化, 這就要求運維人員具備一定的開發能力來編排運維過程並讓它們能 自動運行起來。
• 接口的一致性:雖然我們拆分了服務, 但是業務邏輯上的依賴並不會消除, 只是從 單體應用中的代碼依賴變為了服務間的通信依賴。 而當我們對原有接口進行了一些 修改, 那么交互方也需要協調這樣的改變來進行發布, 以保證接口的正確調用。 我 們需要更完善的接口和版本管理, 或是嚴格地遵循開閉原則。
• 分布式的復雜性:由於拆分后的各個微服務都是獨立部署並運行在各自的進程內, 它們只能通過通信來進行協作, 所以分布式環境的問題都將是微服務架構系統設計 時需要考慮的重要因素, 比如網絡延遲、 分布式事務、 異步消息等。 盡管微服務架構有很多缺點和問題, 但是其實現的敏捷開發和自動化部署等優點依然 被廣大優秀架構師和開發者所青眯, 所以解決這些問題就是這幾年諸多架構大師努力的目 標。 在架構師對於一個大型系統架構的設計與實施的過程中, 面對環境、 資源、 團隊等各 種因素的影響, 幾乎不會出現完全相同的架構設計。 對於微服務架構而言更是如此, 由並沒有一個標准或正式的定義,每位架構師都根據自身理解與實際情況來進行設計,並在 發展的過程中不斷演化與完善。 經過多年的發展,MartinFowler在Microservices 一文中, 提煉出了微服務架構的九大特性,用於指導大家設計架構。
服務組件化
組件,是一個可以獨立更換和升級的單元。 就像 PC 中的 CPU、內存、 顯卡、 硬盤一 樣,獨立且可以更換升級而不影響其他單元。 在微服務架構中,需要我們對服務進行組件化分解。 服務,是一種進程外的組件,它 通過 HTTP 等通信協議進行協作,而不是像傳統組件那樣以嵌入的方式協同工作。 每一個 服務都獨立開發、 部署,可以有效避免一個服務的修改引起整個系統的重新部署。 打一個不恰當的比喻,如果我們的 PC 組件以服務的方式構建,那么只維護主板和一 些必要外設之后,計算能力通過一組外部服務實現,我們只需要告訴 PC 從哪個地址來獲 得計算能力,通過服務定義的計算接口來實現我們使用過程中的計算需求,從而實現 CPU 組件的服務化。 這樣原本復雜的 PC 服務得到了輕量化的實現,我們甚至只需要更換服務 地址就能升級PC 的計算能力。
按業務組織團隊
當決定如何划分微服務時,通常也意味着我們要開始對團隊進行重新規划與組織。 按 以往的方式,我們往往會從技術的層面將團隊划分為多個,比如DBA團隊、運維團隊、后 端團隊、 前端團隊、 設計師團隊等。 若我們繼續按這種方式組織團隊來實施微服務架構開 發,當有一個服務出現問題需要更改時,可能是一個非常簡單的變動,比如對人物描述增 加一個字段,這需要從數據存儲開始考慮一直到設計和前端, 雖然大家的修改都非常小, 但這會引起跨團隊的時間耗費和預算審批。
在實施微服務架構時,需要采用不同的團隊分割方法。 由於每一個微服務都是針對特 定業務的寬棧或是全棧實現,既要負責數據的持久化存儲, 又要負責用戶的接口定義等各 種跨專業領域的職能。 因此,面對大型項目的時候,對於微服務團隊的拆分更加建議按業 務線的方式進行拆分, 一方面可以有效減少服務內部修改所產生的內耗; 另一方面,團隊 邊界可以變得更為清晰。
做 “產品” 的態度
在實施微服務架構的團隊中,每個小團隊都應該以做產品的方式,對其產品的整個生 命周期負責。 而不是以項目的模式,以完成開發與交付並將成果交接給維護者為最終目標。
開發團隊通過了解服務在具體生產環境中的情況, 可以增加他們對具體業務的理解, 比如, 很多時候, 一些業務中發生的特殊或異常情況, 很可能產品經理都並不知曉, 但細 心的開發者很容易通過生產環境發現這些特殊的潛在問題或需求。 所以, 我們需要用做 “產品” 的態度來對待每一個微服務, 持續關注服務的運作情況, 並不斷分析以幫助用戶來改善業務功能。
智能端點與啞管道
在單體應用中, 組件間直接通過函數調用的方式進行交互協作。 而在微服務架構中, 由於服務不在一個進程中, 組件間的通信模式發生了改變, 若僅僅將原本在進程內的方法 調用改成RPC方式的調用, 會導致微服務之間產生煩瑣的通信, 使得系統表現更為糟糕, 所以, 我們需要更粗粒度的通信協議。 在微服務架構中, 通常會使用以下兩種服務調用方式:
• 第一種, 使用 HTTP的 RESTful API或輕量級的消息發送協議, 實現信息傳遞與服 務調用的觸發。
• 第二種, 通過在輕量級消息總線上傳遞消息, 類似 RabbitMQ 等一些提供可靠異步 交換的中間件。
在極度強調性能的情況下, 有些團隊會使用二進制的消息發送協議, 例如 protobuf。 即使是這樣, 這些系統仍然會呈現出 “智能瑞點和啞管道” 的特點, 這 是為了在易讀性與高效性之間取得平衡。當然大多數Web 應用或企業系統並不需 要在這兩者間做出選擇, 能夠荻得易讀性已經是一個極大的勝利了。
一Martin Fowler
去中心化治理 (有點像區塊鏈的概念)
當我們采用集中化的架構治理方案時, 通常在技術平台上都會制定統一的標准, 但是 每一種技術平台都有其短板, 這會導致在碰到短板時, 不得不花費大力氣去解決, 並且可 能因為其底層原因解決得不是很好, 最終成為系統的瓶頸。
在實施微服務架構時, 通過采用輕量級的契約定義接口, 使得我們對於服務本身的具 體技術平台不再那么敏感, 這樣整個微服務架構系統中的各個組件就能針對其不同的業務 特點選擇不同的技術平台, 終千不會出現殺雞用牛刀或是殺牛用指甲鉗的尷尬處境了。
去中心化管理數據
我們在實施微服務架構時, 都希望讓每一個服務來管理其自有的數據庫, 這就是數據 管理的去中心化。 在去中心化過程中, 我們除了將原數據庫中的存儲內容拆分到新的同平台的其他數據 庫實例中之外(如把原本存儲在MySQL中的表拆分后,存儲到多個不同的MySQL實例中), 也可以將一些具有特殊結構或業務特性的數據存儲到一些其他技術的數據庫實例中(如把 日志信息存儲到 MongoDB 中或把用戶登錄信息存儲到 Redis中)。 雖然數據管理的去中心化可以讓數據管理更加細致化, 通過采用更合適的技術可讓數 據存儲和性能達到最優。 但是, 由於數據存儲於不同的數據庫實例中后, 數據一致性也成 為微服務架構中亟待解決的問題之一。分布式事務本身的實現難度就非常大, 所以在微服 務架構中, 我們更強調在各服務之間進行 “無事務” 的調用, 而對於數據一致性, 只要求 數據在最后的處理狀態是一致的即可;若在過程中發現錯誤, 通過補償機制來進行處理, 使得錯誤數據能夠達到最終的一致性。
基礎設施自動化
近年來雲計算服務與容器化技術的不斷成熟,運維基礎設施的工作變得越來越容易。 但是, 當我們實施微服務架構時, 數據庫、 應用程序的個頭雖然都變小了, 但是因為拆分 的原因, 數量成倍增長。 這使得運維人員需要關注的內容也成倍增長, 並且操作性任務也 會成倍增長, 這些問題若沒有得到妥善解決, 必將成為運維人員的噩夢。 所以, 在微服務架構中, 務必從一開始就構建起 “待續交付” 平台來支撐整個實施過 程, 該平台需要兩大內容, 缺一不可。
• 自動化測試:每次部署前的強心劑, 盡可能地獲得對正在運行的軟件的信心。
• 自動化部署:解放煩瑣枯燥的重復操作以及對多環境的配置管理。
容錯設計
在單體應用中, 一般不存在單個組件故障而其他部件還在運行的情況, 通常是一掛全 掛。 而在微服務架構中, 由於服務都運行在獨立的進程中, 所以存在部分服務出現故障, 而其他服務正常運行的情況。 比如, 當正常運作的服務B調用到故障服務A時, 因故障服 務A沒有返回, 線程掛起開始等待, 直到超時才能釋放, 而此時若觸發服務B調用服務A 的請求來自服務C, 而服務 C頻繁調用服務B 時, 由千其依賴服務A, 大量線程被掛起等 待, 最后導致服務A也不能正常服務, 這時就會出現故障的荽延。
所以, 在微服務架構中, 快速檢測出故障源並盡可能地自動恢復服務是必須被設計和考慮的。 通常, 我們都希望在每個服務中實現監控和日志記錄的組件, 比如服務狀態、 斷 路器狀態、 吞吐量、 網絡延遲等關鍵數據的儀表盤等。
演進式設計
通過上面的幾點特征, 我們已經能夠體會到, 要實施一個完美的微服務架構, 需要考 慮的設計與成本並不小, 對千沒有足夠經驗的團隊來說, 甚至要比單體應用付出更多的代 價。
所以, 在很多情況下, 架構師都會以演進的方式進行系統的構建。 在初期, 以單體系 統的方式來設計和實施, 一方面系統體量初期並不會很大, 構建和維護成本都不高。 另一 方面, 初期的核心業務在后期通常也不會發生巨大的改變。 隨着系統的發展或者業務的需 要, 架構師會將一些經常變動或是有一定時間效應的內容進行微服務處理, 並逐漸將原來 在單體系統中多變的模塊逐步拆分出來, 而穩定不太變化的模塊就形成一個核心微服務存 在於整個架構之中。
為什么選擇Spring Cloud
近幾年很多入對於微服務架構的熱情非常高, 但是回頭看 “微服務” 被提及也有很多 年了。 無數的架構師和開發者在實際項目中實踐該設計理念並為此付出了諸多努力, 同時 也分享了他們在微服務架構中針對不同應用場景出現的各種問題的各種解決方案和開源框 架, 其中也不乏國內互聯網企業的傑出貢獻。
• 服務治理:阿里巴巴開源的Dubbo和當當網在其基礎上擴展的DubboX、 Netflix的 Eureka、Apache的Consul等。
• 分布式配置管理:百度的Disconf、 Netflix的Archaius、360的QConf、SpringCloud 的Config、 淘寶的Diamond等。 • 批量任務:當當網的Elastic-Job、 Linkedln的Azkaban、 SpringCloud的Task等。
• 服務跟蹤:京東的Hydra、SpringCloud的Sleuth、Twitter的Zipkin等。 .......
上面列舉了一些在實施微服務架構初期, 就需要被我們考慮進去的問題, 以及針對這 些間題的開源解決方案。 可以看到國內、 國外的技術公司都在貢獻着他們的智慧。 我們搜 索微服務架構的實施方案時會發現, 幾乎大部分的分享主要以理論或是一個粗輪廓框架為 主, 整合了來自不同公司或組織的諸多開源框架, 並加入針對自身業務的一些優化, 所以 找不到一個完全相同的架構方案。
前面我們介紹了一些關於微服務的理念以及特性, 分析了實施微服務的優點和缺點,而這些缺點通常就是這些框架出現的源頭,大家都是為了解決或彌補業務拆分后所引出的 諸多詞題來設計出這些解決方案。而當我們作為一個新手,准備實施微服務架構時,為了 避免踩前輩們踩過的坑,我們不得不在這些核心問題上做出選擇,而選擇又是如此之多, 這必然會導致在做技術選型的初期, 需要花費巨大的調研、 分析與實驗精力。
Spring Cloud的出現,可以說是對微服務架構的巨大 支持和強有力的技術后盾。它不像 我們之前所列舉的框架那樣, 只是解決微服務中的某一個問題,而是一個解決微服務架構 實施的綜合性解決框架,它整合了諸多被廣泛實踐和證明過的框架作為實施的基礎部件, 又在該體系基礎上創建了一些非常優秀的邊緣組件。
打個不太恰當的比喻:我們自己對各個問題選擇框架來實施微服務架構就像在DIY電 腦一樣,我們對各環節的選擇自由度很高, 但是最終結果很有可能因為一條內存質量不行 就點不亮了,總是讓人不怎么放心。當然,如果你是一名高 手,這些自然都不是問題,然 而千軍易得 、 良將難求。而使用Spring Cloud來實施就像直接購買品牌機一樣,在Spring 社區的整合之下,做了大量的兼容性測試,保證了其擁有更好的穩定性,如果要在Spring Cloud架構下使用非原裝組件時,就需要對其基礎有足夠的了解。
Spring Cloud也許對很多已經實施微服務並自成體系的團隊不具備足夠的吸引力,但是 對於還未實施微服務或是未成體系的團隊,這必將是一個非常有吸引力的框架選擇。不論 其項目的發展目標,還是 Spring的強大背景, 亦或其極高的社區活躍度,都是未來企業架 構師必須了解和接觸的重要框架,有一天成為微服務架構的標准解決方案也並非不可能。
下一節:Spring Cloud 介紹