SOA和微服務架構的區別?
微服務架構強調的第一個重點就是業務系統需要徹底的組件化和服務化,原有的單個業務系統會拆分為多 個可以獨立開發,設計,運行和運維的小應用。這些小應用之間通過服務完成交互和集成。每個小應用從 前端web ui,到控制層,邏輯層,數據庫訪問,數據庫都完全是獨立的一套。在這里我們不用組件而用小 應用這個詞更加合適,每個小應用除了完成自身本身的業務功能外,重點就是還需要消費外部其它應用暴 露的服務,同時自身也將自身的能力朝外部發布為服務。 如果一句話來談SOA和微服務的區別,即微服務不再強調傳統SOA架構里面比較重的ESB企業服務總線, 同時SOA的思想進入到單個業務系統內部實現真正的組件化。 把這個核心搞清楚后,再來看下網上找到的對微服務架構的一些定義和闡述: 微服務可以在“自己的程序”中運行,並通過“輕量級設備與HTTP型API進行溝通”。關鍵在於該服務可以 在自己的程序中運行。通過這一點我們就可以將服務公開與微服務架構(在現有系統中分布一個API) 區分開來。在服務公開中,許多服務都可以被內部獨立進程所限制。如果其中任何一個服務需要增加某 種功能,那么就必須縮小進程范圍。在微服務架構中,只需要在特定的某種服務中增加所需功能,而不 影響整體進程。 微服務不需要像普通服務那樣成為一種獨立的功能或者獨立的資源。定義中稱,微服務是需要與業務能 力相匹配,這種說法完全正確。不幸的是,仍然意味着,如果能力模型粒度的設計是錯誤的,那么,我 們就必須付出很多代價。如果你閱讀了Fowler的整篇文章,你會發現,其中的指導建議是非常實用的。 在決定將所有組件組合到一起時,開發人員需要非常確信這些組件都會有所改變,並且規模也會發生變 化。服務粒度越粗,就越難以符合規定原則。服務粒度越細,就越能夠靈活地降低變化和負載所帶來的 影響。然而,利弊之間的權衡過程是非常復雜的,我們要在配置和資金模型的基礎上考慮到基礎設施的 成本問題。 再強調下即: 首先對於應用本身暴露出來的服務,是和應用一起部署的,即服務本身並不單獨部署,服務本身就是業務 組件已有的接口能力發布和暴露出來的。了解到這點我們就看到一個關鍵,即我們在進行單個應用組件設 計的時候,本身在組件內部就會有很大接口的設計和定義,那么這些接口我們可以根據和外部其它組件協 同的需要將其發布為微服務,而如果不需要對外協同我們完全可以走內部API接口訪問模式提高效率。 其次,微服務架構本身來源於互聯網的思路,因此組件對外發布的服務強調了采用HTTP Rest API的方式 來進行。這個也可以看到在互聯網開放能力服務平台基本都采用了Http API的方式進行服務的發布和管理。 從這個角度來說,組件超外部暴露的能力才需要發布為微服務,其本身也是一種封裝后的粗粒度服務。而 不是將組件內部的所有業務規則和邏輯,組件本身的底層數據庫CRUD操作全部朝外部發布。否則將極大 的增加服務的梳理而難以進行整體服務管控和治理。 微服務的基本思想在於考慮圍繞着業務領域組件來創建應用,這些就應用可獨立地進行開發、管理和加 速。在分散的組件中使用微服務雲架構和平台使部署、管理和服務功能交付變得更加簡單。 對於互聯網談到微服務架構一定會談到Devops即開發測試和部署運維的一體化。當我們的單體應用以及拆 分為多個小應用后,雖然整體架構可以松耦合和可擴展,但是如果拆分的組件越多,這些組件之間本身的 集成和部署運維就越復雜。即任何一個組件,當他依賴的外部其它應用組件越多的時候,整個集成,部署 和聯調測試的過程就越復雜。這些如果完全靠我們手工去完成一是增加工作量,一是增加出錯概率。 原來談組件化開發談的最多的是單個組件的持續集成,包括配置環境集成,自動打包部署,自動化的冒煙 測試等。對於微服務架構下首先仍然是要做好單個組件本身的持續集成,其次在這個基礎上增加了多個組 件的打包部署和組件間的集成。里面的核心思想就是Devops的思路,希望能夠實現開發設計到部署運維的 一體化。 由於微服務架構里面強調了單個組件本身是可以在獨立的進程里面運行,各個組件之間在部署的時候就能 夠做到進程級別的隔離。那么一台服務器我們可能需要初始化幾十個甚至更多的進程來進行應用組件的部 署。為了保持進程的隔離性,我們可以用虛擬機,但是當幾十個進程都完全用獨立的虛擬機就不現實的, 2017/9/24 SOA和微服務架構的區別? - 知乎 https://www.zhihu.com/question/37808426 2/7 而這個問題的解決剛好就是利用PaaS平台里面的輕量Docker容器來做這個事情,每個Docker是獨立的容 器剛好又完全做到進程級別的隔離,資源占用率又最小,這些特點剛好滿足微服務架構的開發測試和自動 化部署。 前面這些問題思考清楚后就是考慮所有暴露的微服務是否需要一個統一的服務管控和治理平台,按照當前 微服務架構的整體思路,雖然單個服務的實現和發布仍然是在組件內部完成的,但是這些組件暴露的服務 本身的調用情況,服務本身的安全,日志和流量控制等仍然需要一個統一的SOA服務管理平台來完成。 由於微服務盡量都是通過HTTP API的方式暴露出去的,因此這種服務管理平台不需要像傳統企業內部的 ESB服務總線這么重。但是最基本的服務注冊,服務代理,服務發布,服務簡單的路由,安全訪問和授 權,服務調用消息和日志記錄這些功能還是需要具備。類似淘寶的Dubbo架構,即可以做為微服務架構下 的服務管控平台。 對於這種服務管控平台,核心需要討論的就是服務每次調用本身的消息傳遞,輸入和輸出日志是否需要記 錄,當前就有兩種做法,一種是不記錄,管理平台只負責服務注冊和目錄發布,安全授權,實際的服務訪 問仍然是兩個組件之間的點對點連接完成,這種方式下整個架構下獲取更高的性能,同時服務管理平台也 不容易成為大並發服務訪問下的單點瓶頸;另外一種方式就是完全記錄,在這種方式下就需要考慮服務管 理平台本身的集群化不是,高並發下的性能問題。而個人建議最好的方式還是SOA服務管理平台應該提供 兩種管理能力,同時僅僅對核心的需要Log日志的服務進行日志記錄,而其它服務只提供服務目錄和訪問控 制即可。 ===========2016.6.8日更新,增加Chris Richardson微服務系列讀書筆記 本文為閱讀《Chris Richardson 微服務系列》的閱讀筆記,具體原文參考:「Chris Richardson 微服務系 列」服務發現的可行方案以及實踐案例 , 里面有另外四篇的鏈接,當前daocloud已經更新到第5篇事件驅動架構。 第一篇 微服務架構的優勢和不足 文中強調的單體應用的場景,我在前面很多談組件化和服務化的文章里面已經都談到過了,即一個應用系 統里面的模塊沒有辦法做到徹底解耦,如果要實現按組件單獨部署是不可能的,相互之間仍然有大量內部 不可見依賴而導致了模塊間無法拆分。 那么單體應用本身帶來的問題主要有哪些? 1.系統復雜:內部多個模塊緊耦合,關聯依賴復雜,牽一發而動全身。 2.運維困難:變更或升級的影響分析困難,任何一個小修改都可能導致單體應用整體運行出現故障。 3.無法擴展:無法拆分部署,出現性能瓶頸后往往只能夠增加服務器或增加集群節點,但是DB問題難解決 正是由於這些原因需要考慮引入微服務架構(實質仍然是單個應用本身的組件化和服務化),對於微服務 文章里面有一個詳細說明如下:一個微服務一般完成某個特定的功能,比如訂單管理、客戶管理等。每個 微服務都是一個微型應用,有着自己六邊形架構,包括商業邏輯和各種接口。有的微服務通過暴露 API 被別的微服務或者應用客戶端所用;有的微服務則通過網頁 UI 實現。在運行時,每個實例通常是一個 雲虛擬機或者 Docker 容器。 從這個定義和說明仍然需要做一些關鍵理解,即在我前面談微服務的文章里面談到過的,即核心的幾點包 括了,其一足夠構成一個獨立小應用(從DB到UI),其二微服務應用之間只能通過Service API進行交互,其三一般運行在雲虛擬機或更輕的Docker容器上。 API Gateway,這實際上微服務架構里面的很重要的內容,其作用類似於傳統企業內部的ESB服務總線,只是 更加輕量和高性能來解決微服務的管控和治理問題。而對於負載均衡,緩存,路由,訪問控制,服務代 2017/9/24 SOA和微服務架構的區別? - 知乎 https://www.zhihu.com/question/37808426 3/7 理,監控,日志等都屬於基本的服務管控內容,也是API Gateway需要考慮的核心能力。 Scale Cube的3D模型,描述的相當好,即通過微服務架構實施后擴展性的變化。 1. Y軸:本質是應用的分解,即將傳統的單體應用分解為多個微服務應用。 2. X軸:水平彈性擴展能力,即通過負載均衡來實現水平彈性擴展,但是DB問題無法解決,引入3 3. Z軸:當單個微服務應用引入了DB彈性擴展能力要解決的時候,我們引入了對數據庫進行拆分和DaaS 對於微服務架構的好處前面在講單體應用的問題的時候已經談到了,微服務架構正好是解決這些問題。而 對於微服務架構的不足,簡單總結如下: 1. CAP原則:由於服務無狀態和引入了分布式,較難解決事務一致性問題。 2. 集成復雜:任何徹底的分解都將帶來集成的復雜度,即模塊在集成時候需要外部微服務模塊更多的配 合。 3. 部署問題:稍大項目都涉及到上100個服務節點部署,還涉及到部署后的配置,擴展和監控問題。 第二篇 使用API網關構建微服務 首先說下這篇文章的引入場景,以一個亞馬遜購物網站的手機APP訂單查看界面來舉例,如果是一個單體 應用,那么所有的界面需要獲取信息都通過單體應用統一一個地址提供的多個Service API獲取。但是轉變為微服務架構后可以看到對於會員管理,商品管理,訂單管理,財務結算管理等都已經 拆分為了不同的微服務模塊,需要從不同的服務提供地址調用不同的微服務模塊提供的Service API來返回數據。 在原文里面我們看到對於客戶端和微服務模塊間點對點直接通訊提了三個問題,如下: 1. 問題一:客戶端需求和每個微服務暴露的細粒度 API 不匹配 2. 問題二:部分服務使用的協議對 web 並不友好,如二進制RPC或AMQP消息等。 3. 問題三:會使得微服務難以重構,如服務拆分或服務組合的場景。 那么我們從傳統的ESB能力來對上面三個問題進行一個說明,第一個問題即可能涉及到細粒度的API組合, 類似組合服務無法做;其二是可能存在協議轉換的問 題要解決;其三即服務透明的問題,即需要對客戶端提供一個統一的服務目錄以使底層服務透明。由於以 上問題,引入了API服務網關的概念,再次強調,對於API服務網關即使微服務架構里面的輕量服務總線, 解決服務管控和治理相關問題。文中對API Gateway給出如下說明: API 網關是一個服務器,也可以說是進入系統的唯一節點。這與面向對象設計模式中的 Facade 模式很 像。API 網關封裝內部系統的架構,並且提供 API 給各個客戶端。它還可能還具備授權、監控、負載均衡、緩存、請求分片和管理、靜態響應處理等功能。 API 網關負責服務請求路由、組合及協議轉換。客戶端的所有請求都首先經過 API 網關,然后由它將請求 路由到合適的微服務。API 網關經常會通過調用多個微服務並合並結果來處理一個請求。它可以在 web 協議(如 HTTP 與 WebSocket)與內部使用的非 web 友好協議之間轉換。 API 網關還能為每個客戶端提供一個定制的 API。通常,它會向移動客戶端暴露一個粗粒度的 API。以產品 詳情的場景為例,API 2017/9/24 SOA和微服務架構的區別? - 知乎 https://www.zhihu.com/question/37808426 4/7 網關可以提供一個端點(/productdetails?productid=xxx),使移動客戶端可以通過一個請求獲取所有的產 品詳情。API 網關通過調用各個服務(產品信息、推薦、評論等等)並合並結果來處理請求。 API網關的優點和缺點 對於API網關的優點,其實是類似傳統ESB企業服務總線的優點,即實現服務透明,同時對於服務運行過程 中的日志,安全,路由,緩存等問題進行統一配置和處理,而不需要每個微服務API實現時都去考慮。如開 源的Dubbo服務總線即可以看作是一個API網關的實現。 API網關和ESB的一些重要區別點在於API網關更加輕量和高性能,它不需要去考慮太多遺留系統和諸多協 議的適配,其次也不需要考慮服務集成過程中的大 量數據轉換和映射。同時為了提升服務網關的性能,一般API網關在實現過程中不會去記錄詳細的數據傳輸 日志,或者類似Dubbo架構數據傳輸根本就不會通 過API網關。 使用 API 網關的最大優點是,它封裝了應用程序的內部結構。客戶端只需要同網關交互,而不必調用特定 的服務。API 網關也有一些不足。它增加了一個我們必須開發、部署和維護的高可用組件。還有一個風險是,API 網關 變成了開發瓶頸。 簡單來說,在我們期望的去中心化和全分布式架構中,網關又成了一個中心點或瓶頸點,正是由於這個原 因我們在網關設計的時候必須考慮即使API Gateway宕機也不要影響到服務的調用和運行。 API網關的設計和實現 對於大多數應用程序而言,API 網關的性能和可擴展性都非常重要。因此,將 API 網關構建在一個支持異 步、I/O 非阻塞的平台上是合理的。有多種不同的技術可以實現一個可擴展的 API 網關。在 JVM 上,可以使用一 種基於 NIO 的框架,比如 Netty、Vertx、Spring Reactor 或 JBoss Undertow 中的一種。一個非常流行的非 JVM 選項是 Node.js,它是一個基於 Chrome JavaScript 引擎構建的平台。 另一個方法是使用 NGINX Plus。NGINX Plus 提供了一個成熟的、可擴展的、高性能 web 服務器和一個易於部署的、可配置可編程的反向代理。NGINX Plus 可以管理身份驗證、訪問控制、負載均衡請求、緩存響應,並提供應用程序可感知的健康檢查和監控。 對於API網關需要實現底層多個細粒度的API組合的場景,文章推薦采用響應式編程模型進行而不是傳統的 異步回調方法組合代碼。其原因除了采用回調方式導致的代碼混亂外,還有就是對於API組合本身可能存在 並行或先后調用,對於采用回調方式往往很難控制。 基於微服務的應用程序是一個分布式系統,必須使用一種進程間通信機制。有兩種類型的進程間通信機制 可供選擇。一種是使用異步的、基於消息傳遞的機制。有些實現使用諸如 JMS 或 AMQP 那樣的消息代理,而其它的實現(如 Zeromq)則沒有代理,服務間直接通信。另一種進程 間通信類型是諸如 HTTP 或 Thrift 那樣的同步機制。通常,一個系統會同時使用異步和同步兩種類型。它甚至還可能使用同一類型 的多種實現。總之,API 網關需要支持多種通信機制。 2017/9/24 SOA和微服務架構的區別? - 知乎 https://www.zhihu.com/question/37808426 5/7 注:如果服務是同步調用可以看到微服務模塊之間本身是沒有徹底解耦的,即如果A依賴B提供的API,如 果B提供的服務不可用將直接影響到A不可用。除非同步服務調用在API網關層或客戶端做了相應的緩存。 因此為了徹底解耦,在微服務調用上更建議選擇異步方式進行。 對於大多數基於微服務的應用程序而言,實現 API 網關,將其作為系統的唯一入口很有必要。API 網關負責服務請求路由、組合及協議轉換。它為每個應用程序客戶端提供一個定制的 API。API 網關還可以通過返回緩存數據或默認數據屏蔽后端服務失敗。 第三篇 微服務架構中的進程間通信 基於微服務的分布式應用是運行在多台機器上的;一般來說,每個服務實例都是一個進程。因此,如下圖 所示,服務之間的交互必須通過進程間通信(IPC)來實現。 對於微服務架構的交互模式,文章從兩個維度進行了描述,即 一對一:每個客戶端請求有一個服務實例來響應。 一對多:每個客戶端請求有多個服務實例來響應。 同步模式:客戶端請求需要服務端即時響應,甚至可能由於等待而阻塞。 異步模式:客戶端請求不會阻塞進程,服務端的響應可以是非即時的。 對於分為這兩個維度進行描述意義不太大,對於同步模式往往只能是1對1,而且還需要同步等待容易引起 阻塞,而對於異步模塊往往采用消息機制來實現,同時配合消息中間件可以進一步實現消息的發布訂閱。 而對於EDA事件驅動架構要看到其本質也是伊布消息中間件和消息的發布訂閱。 異步消息機制可以做到最大化的解耦,對於數據CUD的場景可以看到是比較容易通過異步消息機制實現 的,但是會進一步引入事務一致性問題,即在采用異步消息 機制后往往通過BASE事務最終一致性來解決事務層面的問題。而對於查詢功能可以看到是比較難通過異步 消息API實現的,在引入這個之前可以看到需要考慮 兩方面的問題並解決。 其一是服務網關需要有數據緩存能力,以解決無法從源端獲取數據的場景。其二是前端開發框架本身需要 支持異步調用和數據裝載模式,特別是對於數據查詢功能對於用戶來講,在前端的感受仍然需要時同步 的。即通過異步方式返回了查詢數據后可以動態刷新前端展示界面。 服務版本的問題:這是不可避免要遇到的問題,特別是對於RestAPI調用,由於Json格式本身無Schema返 回更加容易忽視了對服務 版本的管理和控制。要知道對於Json數據格式變化仍然會導致RestAPI調用后處理失敗。因此服務版本仍 然采用大小版本管理機制比較好,對於小版本變 更則直接對原有服務進行覆蓋同時對所有受影響的服務消費端進行升級;而對於大版本升級則本質是新增 加了一個新服務,而對於舊版本服務逐步遷移和替代。 處理局部失敗:文中提到了Netfilix的服務解決方案,對於失敗問題的解決要注意常用的仍然是服務超時設 置,斷路器機制,流量控制,緩存數據或默認值返回等。不論采用哪種失敗處理策略,都需要考慮應該盡 量減少服務調用失敗或超時對最終用戶造成的影響。 基於請求/響應的同步 IPC 使用同步的、基於請求/響應的 IPC 機制的時候,客戶端向服務端發送請求,服務端處理請求並返回響應。一些客戶端會由於等待服務端響應 而被阻塞,而另外一些客戶端可能使用異步的、基於事件驅動的客戶端代碼,這些代碼可能通過 Future 或者 Rx Observable 2017/9/24 SOA和微服務架構的區別? - 知乎 https://www.zhihu.com/question/37808426 6/7 封裝。然而,與使用消息機制不同,客戶端需要響應及時返回。這個模式中有很多可選的協議,但最常見 的兩個協議是 REST 和 Thrift。 Thrift 也能夠讓你選擇傳輸協議,包括原始 TCP 和 HTTP。原始 TCP 比 HTTP 更高效,然而 HTTP 對於防火牆、瀏覽器和使用者來說更友好。文中對於兩種實現方式已經描述的相當詳細,可以看到當前互 聯網OpenAPI平台和微服務架構實現中仍然是大量以采用Rest API接口為主。 而對於消息格式的選擇,可以看到在使用RestAPI接口的時候,更多的是采用了Json消息格式而非XML, 對於SOAP WebService則更多采用了XML消息格式。如果采用Thrift則還可以采用二進制消息格式以提升性能。 第四篇 服務發現的可行方案以及實踐案例 首先還是先說場景,看似簡單的服務注冊和服務目錄庫管理為何會變復雜,其主要的原因還是在結合了雲 端PaaS和Docker容器部署后,對於微服務模塊部 署完成后提供出來的IP地址是動態在變化的,包括模塊在進行動態集群擴展的時候也需要動態接入新的服 務提供IP地址。正是由於這個原因引入了服務發現和管 理的困難度。 在文章中提到了兩種服務發現模式,即客戶端發現模式和服務端發現模式,分開描述如下: 服務客戶端發現模式 使用客戶端發現模式時,客戶端決定相應服務實例的網絡位置,並且對請求實現負載均衡。客戶端查詢服 務注冊表,后者是一個可用服務實例的數據庫;然后使用負 載均衡算法從中選擇一個實例,並發出請求。客戶端從服務注冊服務中查詢,其中是所有可用服務實例的 庫。客戶端使用負載均衡算法從多個服務實例中選擇出一 個,然后發出請求。 注:這是類似Dubbo實現機制一樣的兩階段模式,即任何一個服務的消費都需要分兩個步驟進行,第一步 首先是訪問服務注冊庫(更多是API GateWay提供的一個能力)返回一個已經動態均衡后的服務可用地址,第二步即客戶端和該地址直接建立 連接進行服務消費和訪問。 在這種模式的實現中有兩個重點,其一是動態負載均衡算法,其二是服務網關需要能夠對原始服務提供點 進行實時的心跳檢測以確定服務提供的可用性。 Netflix OSS 是客戶端發現模式的絕佳范例。Netflix Eureka 是一個服務注冊表,為服務實例注冊管理和查詢可用實例提供了 REST API 接口。Netflix Ribbon 是 IPC 客戶端,與 Eureka 一起實現對請求的負載均衡。 缺點:底層的IP雖然動態提供出去了,但是最終仍然暴露給了服務消費方,再需要進一步做安全和防火牆 隔離的場景下顯然是不能滿足要求的。 服務端發現模式 客戶端通過負載均衡器向某個服務提出請求,負載均衡器查詢服務注冊表,並將請求轉發到可用的服務實 2017/9/24 SOA和微服務架構的區別? - 知乎 https://www.zhihu.com/question/37808426 7/7 例。如同客戶端發現,服務實例在服務注冊表中注冊或注銷。在原文中有圖示,基本看圖就清楚了,即在 服務注冊庫前新增加了一個Load Balancer節點。注:這兩個節點感覺是可以合並到API GateWay的能力中去的。 服務端發現模式兼具優缺點。它最大的優點是客戶端無需關注發現的細節,只需要簡單地向負載均衡器發 送請求,這減少了編程語言框架需要完成的發現邏輯。並且 如上文所述,某些部署環境免費提供這一功能。這種模式也有缺點。除非負載均衡器由部署環境提供,否 則會成為一個需要配置和管理的高可用系統組件。 服務注冊表 服務注冊表需要高可用而且隨時更新。客戶端能夠緩存從服務注冊表中獲取的網絡地址,然而,這些信息 最終會過時,客戶端也就無法發現服務實例。因此,服務注冊表會包含若干服務端,使用復制協議保持一 致性。 首先可以看到服務注冊表本身不能是單點,否則存在單點故障,當服務注冊表有多台服務器的時候同時需 要考慮服務注冊庫信息在多台機器上的實時同步和一致。我們操作和配置服務注冊信息的時候往往只會在 一個統一的服務管控端完成。 其次如果服務注冊服務器宕機是否一定影響到服務本身的消費和調用,如果考慮更高的整體架構可用性, 還可以設計對於服務注冊庫信息在客戶端本地進行緩存,當服務注冊表無法訪問的時候可以臨時讀取本地 緩存的服務注冊庫信息並發起服務訪問請求。 對於服務注冊表,文章提供了三種選擇,感覺最常用的實現仍然是基於ZooKeeper進行的。 Etcd – 高可用、分布式、一致性的鍵值存儲,用於共享配置和服務發現。 Consul – 發現和配置的服務,提供 API 實現客戶端注冊和發現服務。 Apache ZooKeeper – 被分布式應用廣泛使用的高性能協調服務。 如前所述,服務實例必須在注冊表中注冊和注銷。注冊和注銷有兩種不同的方法。方法一是服務實例自己 注冊,也叫自注冊模式(self-registration pattern);另一種是采用管理服務實例注冊的其它系統組件,即第三方注冊模式