1. 程式人生 > 其它 >laas、paas、saas、單體應用、微服務、分散式、soa架構、微服務實戰、rpc、CAP 定理、BASE 理論

laas、paas、saas、單體應用、微服務、分散式、soa架構、微服務實戰、rpc、CAP 定理、BASE 理論

一 IaaS基礎設施服務

IaaS: Infrastructure-as-a-Service(基礎設施即服務)

第一層叫做IaaS,有時候也叫做Hardware-as-a-Service,幾年前如果你想在辦公室或者公司的網站上執行一些企業應用,你需要去買伺服器,或者別的高昂的硬體來控制本地應用,讓你的業務執行起來。

但是現在有IaaS,你可以將硬體外包到別的地方去。IaaS公司會提供場外伺服器,儲存和網路硬體,你可以租用。節省了維護成本和辦公場地,公司可以在任何時候利用這些硬體來執行其應用。

一些大的IaaS公司包括Amazon, Microsoft, VMWare, Rackspace和Red Hat.

二 paas平臺即服務

第二層就是所謂的PaaS,某些時候也叫做中介軟體。你公司所有的開發都可以在這一層進行,節省了時間和資源。

PaaS公司在網上提供各種開發和分發應用的解決方案,比如虛擬伺服器和作業系統。這節省了你在硬體上的費用,也讓分散的工作室之間的合作變得更加容易。網頁應用管理,應用設計,應用虛擬主機,儲存,安全以及應用開發協作工具等。

一些大的PaaS提供者有Google App Engine,Microsoft Azure,Force.com,Heroku,Engine Yard。最近興起的公司有AppFog, Mendix 和 Standing Cloud

三saas軟體即服務

第三層也就是所謂SaaS。這一層是和你的生活每天接觸的一層,大多是通過網頁瀏覽器來接入。任何一個遠端伺服器上的應用都可以通過網路來執行,就是SaaS了。

你消費的服務完全是從網頁如Netflix, MOG, Google Apps, Box.net, Dropbox或者蘋果的iCloud那裡進入這些分類。儘管這些網頁服務是用作商務和娛樂或者兩者都有,但這也算是雲技術的一部分。

一些用作商務的SaaS應用包括Citrix的GoToMeeting,Cisco的WebEx,Salesforce的CRM,ADP,Workday和SuccessFactors

四 總結

iass基礎設施服務(組裝機):你買了一大堆電腦配件,cpu 主機板..然後組裝完成後 裝上系統就可以上網。還要自己提供場地 環境 paas平臺即服務(品牌機):買回來開機就行。需要自己提供場地,和環境(電源) saas軟體即服務(去網咖):電腦,場地,環境(電源,網線,飲料)都是網咖提供的服務

一 單體應用

我們假設,您開始開發一個打車應用。

該新應用是一個模組化的六邊形架構,如下圖(一個簡單的打車應用)所示:

該應用的核心是由模組實現的業務邏輯,它定義了服務、領域物件和事件。圍繞核心的是與外部世界介面對接的介面卡。介面卡示例包括資料庫訪問元件、生產和消費訊息的訊息元件和暴露了 API 或實現了一個 UI 的 web 元件。

儘管有一個邏輯模組化架構,但應用程式被作為一個單體進行打包和部署。實際格式取決於應用程式的語言和框架。例如,許多 Java 應用程式被打包成 WAR 檔案部署在如 Tomcat 或者 Jetty 之類的應用伺服器上。其他 Java 應用程式被打包成自包含 (self-contained) 的可執行 JAR。類似地, Rails 和 Node.js 應用程式被打包為有目錄層次的結構

以這種風格編寫的應用是很常見的。他們很容易開發,因為我們的 IDE 和其他工具就是專注於構建單體應用。這些應用程式也很容易測試, 您可以通過簡單地啟動並使用如 Selenium 測試包來測試 UI 以輕鬆地實現端到端 (end-to-end) 測試。單體應用同樣易於部署。您只需拷貝打包好的應用程式到伺服器上。您還可以通過執行多個副本和結合負載均衡器來擴充套件應用。在專案的早期階段,它可以良好運作

二 單體應用的缺陷

成功的應用有一個趨勢,隨著時間推移而變得越來越臃腫。你的開發團隊在每個階段都要實現更多的使用者需求,這意味著需要添加了許多行程式碼。

幾年之後,小而簡單的應用將會逐漸成長成一個龐大的單體。例如某團隊,他正在編寫一個工具,該工具用於從他們的數百萬行程式碼 (lines of code, LOC) 應用中分析出數千個 模組。這是大量開發者在多年齊心協力下創造出了這樣的野獸。

一旦您的應用程式成為了一個龐大、複雜的單體,你的開發組織可能會陷入了一個痛苦的境地,敏捷開發和交付的任何一次嘗試都將原地徘徊。一個主要問題是應用程式實在非常複雜。對於任何一個開發人員來說顯得過於龐大,這是可以理解的。最終,正確修復 bug 和實現新功能變得非常困難而耗時。此外, 這種趨勢就像是往下的螺旋。如果基本程式碼都令人難以理解,那麼改變也不會變得正確,您最終得到的將是一個巨大且不可思議的大泥球。

應用程式的規模也將減緩發展。應用程式越大,啟動時間越長。一個應用啟動時間為 12 分鐘,有的甚至40 分鐘以上。如果開發人員經常要重啟應用伺服器,那麼很大一部分時間都是在等待中度過,他們的生產力將受到限制。

另一個大問題是,複雜的單體應用本身就是持續部署的障礙。如今, SaaS 應用發展到了可以每天多次將變更推送到生產環境中。這對於複雜的單體來說非常困難,因為您需要重新部署整個應用程式才能更新其中任何一部分。 聯想到之前提到的漫長啟動時間,這也不會是什麼好事。此外,因變更所產生的影響通常不是很明確,您很可能需要做大量的手工測試。因此,持續部署是不可能做到的。

當不同模組存在資源需求衝突時,單體應用可能難以擴充套件。例如,一個模組可能會執行 CPU 密集型影象處理邏輯,理想情況下是部署在 Amazon EC2 Compute Optimized 例項中。另一個模組可能是一個記憶體資料庫,最適合部署到 EC2 Memory-optimized 例項。然而, 由於這些模組被部署在一起,您必須在硬體選擇上做出妥協。

單體應用的另一個問題是可靠性。因為所有模組都執行在同一程序中。任何模組的一個 bug,比如記憶體洩漏,可能會拖垮整個程序。此外,由於應用程式的所有例項都是相同的,該錯誤將影響到整個應用的可用性。

最後但同樣重要,單體應用使得采用新框架和語言變得非常困難。例如,我們假設您有 200 萬行程式碼使用了 XYZ 框架編寫。如果使用較新的 ABC 框架來重寫整個應用,這將非常昂貴(在時間和成本方面),即使框架非常好。因此,這對於採用新技術是一個非常大的障礙。在專案開始時, 您無論選擇何種新技術都會感到困擾。

總結一下:你有一個成功的關鍵業務應用程式,它已經發展成為一個只有少數開發人員(如果有的話)能夠理解的巨大單體。它使用了過時、非生產性技術編寫,這使得招聘優秀開發人員變得非常困難。應用程式變得難以擴充套件,不可靠。因此敏捷開發和應用交付是不可能的。

一 微服務概念

微服務架構是一種架構概念,旨在通過將功能分解到各個離散的服務中以實現對解決方案的解耦。它的主要作用是將功能分解到離散的各個服務當中,從而降低系統的耦合性,並提供更加靈活的服務支援。

概念

把一個大型的單個應用程式和服務拆分為數個甚至數十個的支援微服務,它可擴充套件單個元件而不是整個的應用程式堆疊,從而滿足服務等級協議。

定義

圍繞業務領域元件來建立應用,這些應用可獨立地進行開發、管理和迭代。在分散的元件中使用雲架構和平臺式部署、管理和服務功能,使產品交付變得更加簡單。

本質

用一些功能比較明確、業務比較精練的服務去解決更大、更實際的問題。

PS: 微服務這個概念是 2012 年出現的,作為加快 Web 和移動應用程式開發程序的一種方法,2014 年開始受到各方的關注,同年為微服務的元年;

三 微服務解決複雜問題

許多如 Amazon、 eBay 和 Netflix 這樣的組織,已經採用現在所謂的微服務架構模式解決了這個問題,而不是構建一個臃腫的單體應用。它的思路是將應用程式分解成一套較小的互連服務。一個服務通常實現了一組不同的特性或功能,例如訂單管理、客戶管理等。每一個微服務都是一個迷你應用,它自己的六邊形架構包括了業務邏輯以及多個介面卡。

一些微服務會暴露一個供其他微服務或應用客戶端消費的 API。其他微服務可能實現了一個 web UI。在執行時,每個例項通常是一個雲虛擬機器 (virtual machine, VM) 或者一個 Docker 容器。

例如,前面描述的系統可能分解成如下圖(一個單體應用分解成微服務) 所示:

應用程式的每個功能區域現在都由自己的微服務實現。此外,Web 應用程式被劃分為一組更簡單的 Web 應用程式。例如,以我們的計程車為例,一個是乘客的應用,一個是司機的應用。這使得它更容易地為特定的使用者、司機、裝置或者專門的用例部署不同的場景。每個後端服務暴露一個 REST API,大部分服務消費的 API 由其他服務提供。例如, Driver Management 使用了 Notification 伺服器來通知一個可用司機一個可選路程。UI 服務呼叫了其他服務來渲染頁面。服務也可以使用非同步、基於訊息的通訊。

一些 REST API 也暴露給移動端應用以供司機和乘客使用。然而,應用不能直接訪問後端服務。相反,他們之間的通訊是由一個稱為 API 閘道器 (API Gateway) 的中介負責。 API 閘道器負責負載均衡、快取、訪問控制、 API 計量和監控, 可以通過使用 NGINX 來實現。

開發和交付中的伸縮立方:

微服務架構模式相當於此伸縮立方的 Y 軸座標,此立方是一個來自《架構即未來》 的三維伸縮模型。另外兩個座標軸是由執行多個相同應用程式副本的負載均衡器組成的X 軸座標和 Z 軸座標(或資料分割槽) ,其中請求的屬性(例如,一行記錄的主鍵或者客戶標識) 用於將請求路由到特定的伺服器。

在執行時,X 座標軸上執行著服務的多個例項,每個服務配合負載均衡器以滿足吞吐量和可用性。某些應用程式也有可能使用 Z 座標軸來進行分割槽服務。下圖展示瞭如何用 Docker 將 Trip Management 服務部署到 Amazon EC2 上執行。

使用 Docker 部署 Trip Management 服務:

在執行時,Trip Management 服務由多個服務例項組成,每個服務例項是一個 Docker容器。為了實現高可用,容器是在多個雲虛擬機器上執行的。服務例項的之前是一個類似 NGINX 的負載均衡器,用於跨例項分發請求。負載均衡器也可以處理其他問題,如快取、訪問控制、API 度量和監控。

微服務架構模式明顯影響到了應用程式與資料庫之間的關係。與其他共享單個數據庫模式 (schema) 服務有所不同, 其每一個服務都有自己的資料庫模式。一方面,這種做法與企業級資料庫資料模型的想法相背,此外,它經常導致部分資料冗餘。然而,如果您想從微服務中受益,每一個服務都應該有自己的資料庫模式。因為它能實現鬆耦合。下圖展示了資料庫架構示例應用程式。

每個服務都擁有各自的資料庫。而且,服務可以使用一種最適合其需求、號稱多語言持久架構 (polyglot persistence architecture ) 的資料庫。例如,DriverManagement,要找到與潛在乘客接近的司機,就必須使用支援高效地理查詢的資料庫。

打車應用的資料庫架構:

從表面上看,微服務架構模式類似於 SOA。微服務是由一組服務組成。然而,換另一種方式去思考微服務架構模式,它是沒有商業化的 SOA,沒有整合 Web 服務規範 (WS-) 和企業服務匯流排 (Enterprise Service Bus, ESB) 。基於微服務的應用支援更簡單、輕量級的協議,例如,REST,而不是 WS-。他們也儘量避免使用 ESB,而是實現微服務本身具有類似 ESB 的功能。微服務架構也拒絕了 SOA 的其他部分,例如,資料訪問規範模式概念。

四 微服務的優點

微服務架構模式有許多非常好的地方。

第一,它解決了複雜問題。它把可能會變得龐大的單體應用程式分解成一套服務。雖然功能數量不變,但是應用程式已經被分解成可管理的塊或者服務。每個服務都有一個明確定義邊界的方式,如遠端過程呼叫(RPC)驅動或訊息驅動 API。微服務架構模式強制一定程度的模組化,實際上,使用單體程式碼來實現是極其困難的。因此,使用微服務架構模式,個體服務能被更快地開發,並更容易理解與維護。

第二,這種架構使得每個服務都可以由一個團隊獨立專注開發。開發者可以自由選擇任何符合服務 API 契約的技術。當然,更多的組織是希望通過技術選型限制來避免完全混亂的狀態。然而,這種自由意味著開發人員不再有可能在這種自由的新專案開始時使用過時的技術。當編寫一個新服務時,他們可以選擇當前的技術。此外,由於服務較小,使用當前技術重寫舊服務將變得更加可行。

第三,微服務架構模式可以實現每個微服務獨立部署。開發人員根本不需要去協調部署本地變更到服務。這些變更一經測試即可立即部署。比如,UI 團隊可以執行 A|B 測試,並快速迭代 UI 變更。微服務架構模式使得持續部署成為可能。

最後,微服務架構模式使得每個服務能夠獨立擴充套件。您可以僅部署滿足每個服務的容量和可用性約束的例項數目。此外,您可以使用與服務資源要求最匹配的硬體。例如,您可以在 EC2 Compute Optimized 例項上部署一個 CPU 密集型影象處理服務,並且在 EC2 Memory-optimized 例項上部署一個記憶體資料庫服務。

五 微服務缺點

就像 Fred Brooks 大約在 30 年前寫的《人月神話》中說的,沒有銀彈。與其他技術一樣,微服務架構模式也存在著缺點。其中一個缺點就是名稱本身。微服務這個術語的重點過多偏向於服務的規模。事實上,有些開發者主張構建極細粒度的 10 至 100 LOC(程式碼行) 服務,雖然這對於小型服務可能比較好,但重要的是要記住,小型服務只是一種手段,而不是主要目標。微服務的目標在於充分分解應用程式以方便應用敏捷開發和部署。

微服務另一個主要缺點是由於微服務是一個分散式系統,其使得整體變得複雜。開發者需要選擇和實現基於訊息或者 RPC 的程序間通訊機制。此外,由於目標請求可能很慢或者不可用,他們必須要編寫程式碼來處理區域性故障。雖然這些並不是很複雜、高深,但模組間通過語言級方法/過程呼叫相互呼叫,這比單體應用要複雜得多。

微服務的另一個挑戰是分割槽資料庫架構。更新多個業務實體的業務事務是相當普遍的。這些事務在單體應用中的實現顯得微不足道,因為單體只存在一個單獨的資料庫。在基於微服務的應用程式中,您需要更新不同服務所用的資料庫。通常不會選擇分散式事務,不僅僅是因為 CAP 定理。他們根本不支援如今高度可擴充套件的 NoSQL 資料庫和訊息代理。您最後不得不使用基於最終一致性的方法,這對於開發人員來說更具挑戰性。

測試微服務應用程式也很複雜。例如,使用現代框架如 Spring Boot,只需要編寫一個測試類來啟動一個單體 web 應用程式並測試其 REST API。相比之下,一個類似的測試類對於微服務來說需要啟動該服務及其所依賴的所有服務,或者至少為這些服務配置存根。再次宣告,雖然這不是一件高深的事情,但不要低估了這樣做的複雜性。

微服務架構模式的另一個主要挑戰是實現了跨越多服務變更。例如,我們假設您正在實現一個變更服務 A、服務 B 和 服務 C 的需求,其中 A 依賴於 B,且 B 依賴於 C。在單體應用程式中,您可以簡單地修改相應的模組、整合變更並一次性部署他們。相反,在微服務中您需要仔細規劃和協調出現的變更至每個服務。例如,您需要更新服務 C,然後更新服務 B,最後更新服務 A。幸運的是,大多數變更只會影響一個服務,需要協調的多服務變更相對較少。

部署基於微服務的應用程式也是相當複雜的。一個單體應用可以很容易地部署到基於傳統負載均衡器的一組相同伺服器上。每個應用程式例項都配置有基礎設施服務的位置(主機和埠),比如資料庫和訊息代理。相比之下,微服務應用程式通常由大量的服務組成。例如,據 Adrian Cockcroft 瞭解到,Hailo 擁有 160 個不同的服務,Netflix 擁有的服務超過 600 個。

每個服務都有多個執行時例項。還有更多的移動部件需要配置、部署、擴充套件和監控。此外,您還需要實現服務發現機制,使得服務能夠發現需要與之通訊的任何其他服務的位置(主機和埠)。比較傳統麻煩的基於票據(ticket-based)和手動的操作方式無法擴充套件到如此複雜程度。因此,要成功部署微服務應用程式,需要求開發人員能高度控制部署方式和高度自動化。

一種自動化方式是使用現成的平臺即服務(PaaS),如 Cloud Foundry。PaaS 為開發人員提供了一種簡單的方式來部署和管理他們的微服務。它讓開發人員避開了諸如採購和配置 IT 資源等煩惱。同時,配置 PaaS 的系統人員和網路專業人員可以確保達到最佳實踐以落實公司策略。

自動化微服務部署的另一個方式是開發自己的 PaaS。一個普遍的起點是使用叢集方案,如 Kubernetes,與 Docker 等容器技術相結合。

六 小結

構建複雜的微服務應用程式本質上是困難的。單體架構模式只適用於簡單、輕量級的應用程式,如果您使用它來構建複雜應用,您最終會陷入痛苦的境地。微服務架構模式是複雜、持續發展應用的一個更好的選擇。儘管它存在著缺點和實現挑戰。

一 系統架構需要遵循的三個標準

  • 提高敏捷性:及時響應業務需求,促進企業發展

  • 提升使用者體驗:提升使用者體驗,減少使用者流失

  • 降低成本:降低增加產品、客戶或業務方案的成本

二 傳統的開發模式

先來看看傳統的 WEB 開發方式,通過對比比較容易理解什麼是 微服務架構。和 微服務 相對應的,這種方式一般被稱為 單體式開發(Monolithic)

既所有的功能打包在一個 WAR 包裡,基本沒有外部依賴(除了容器),部署在一個 JavaEE 容器(Tomcat,JBoss,WebLogic)裡,包含了 DO/DAO,Service,UI 等所有邏輯。

優點

  • 開發簡單,集中式管理

  • 基本不會重複開發

  • 功能都在本地,沒有分散式的管理和呼叫消耗

缺點

  • 效率低:開發都在同一個專案改程式碼,相互等待,衝突不斷

  • 維護難:程式碼功功能耦合在一起,新人不知道何從下手

  • 不靈活:構建時間長,任何小修改都要重構整個專案,耗時

  • 穩定性差:一個微小的問題,都可能導致整個應用掛掉

  • 擴充套件性不夠:無法滿足高併發下的業務需求

三 微服務架構

目的

有效的拆分應用,實現敏捷開發和部署

開發和交付中的伸縮立方

X軸: 執行多個負載均衡器之後的執行例項 Y軸: 將應用進一步分解為微服務(分庫) Z軸: 大資料量時,將服務分割槽(分表)

一 分散式架構

分散式服務顧名思義服務是分散部署在不同的機器上的,一個服務可能負責幾個功能,是一種面向SOA架構的,服務之間也是通過rpc來互動或者是webservice來互動的。邏輯架構設計完後就該做物理架構設計,系統應用部署在超過一臺伺服器或虛擬機器上,且各分開部署的部分彼此通過各種通訊協議互動資訊,就可算作分散式部署,生產環境下的微服務肯定是分散式部署的,分散式部署的應用不一定是微服務架構的,比如叢集部署,它是把相同應用複製到不同伺服器上,但是邏輯功能上還是單體應用。

二 微服務架構

微服務相比分散式服務來說,它的粒度更小,服務之間耦合度更低,由於每個微服務都由獨立的小團隊負責,因此它敏捷性更高,分散式服務最後都會向微服務架構演化,這是一種趨勢, 不過服務微服務化後帶來的挑戰也是顯而易見的,例如服務粒度小,數量大,後期運維將會很難

微服務架構是一項在雲中部署應用和服務的新技術。大部分圍繞微服務的爭論都集中在容器或其他技術是否能很好的實施微服務,而紅帽說API應該是重點。

微服務可以在“自己的程式”中執行,並通過“輕量級裝置與HTTP型API進行溝通”。關鍵在於該服務可以在自己的程式中執行。通過這一點我們就可以將服務公開與微服務架構(在現有系統中分佈一個API)區分開來。在服務公開中,許多服務都可以被內部獨立程序所限制。如果其中任何一個服務需要增加某種功能,那麼就必須縮小程序範圍。在微服務架構中,只需要在特定的某種服務中增加所需功能,而不影響整體程序的架構。

三 區別

分散式的方式是根據不同機器不同業務。

將一個大的系統劃分為多個業務模組,業務模組分別部署到不同的機器上,各個業務模組之間通過介面進行資料互動。區別分散式的方式是根據不同機器不同業務。

微服務更加強調單一職責、輕量級通訊(HTTP)、獨立性並且程序隔離。

微服務與分散式的細微差別是,微服務的應用不一定是分散在多個伺服器上,他也可以是同一個伺服器。

四 分散式是否屬於微服務?

不一定,如果一個很大應用,拆分成三個應用,但還是很龐大,雖然分散式了,但不是微服務。。微服務核心要素是微小。

五 微服務架構是分散式服務架構的子集

微服務架構通過更細粒度的服務切分,使得整個系統的迭代速度並行程度更高,但是運維的複雜度和效能會隨著服務的粒度更細而增加。

六 總結

# 分散式服務架構
強調的是服務化以及服務的分散化,重在資源共享與加快計算機計算速度
# 微服務
更強調服務的專業化和精細分工,重在解耦合,使每個模組都獨立;
# 從實踐的角度來看
微服務架構通常是分散式服務架構,反之則未必成立。
所以,選擇微服務通常意味著需要解決分散式架構的各種難題。
# 分散式:分散壓力。微服務:分散能力

一 SOA注重重用,微服務注重重寫

SOA 的主要目的是為了企業各個系統更加容易地融合在一起。

微服務通常由重寫一個模組開始。要把整個巨石型的應用重寫是有很大的風險的,也不一定必要。我們向微服務遷移的時候通常從耦合度最低的模組或對擴充套件性要求最高的模組開始。

把它們一個一個剝離出來用敏捷地重寫,可以嘗試最新的技術和語言和框架,然後 單獨佈署。它通常不依賴其他服務。微服務中常用的 API Gateway 的模式主要目的也不是重用程式碼。

而是減少客戶端和服務間的往來。API gateway 模式不等同與 Facade 模式,我們可以使用如 Future 之類的呼叫,甚至返回不完整資料。

二 SOA注重水平服務,微服務注重垂直服務

SOA 設計喜歡給服務分層(如 Service Layers 模式)。我們常常見到一個 Entity 服務層的設計,美其名曰 Data Access Layer。這種設計要求所有的服務都通過這個 Entity 服務層。來獲取資料。這種設計非常不靈活,比如每次資料層的改動都可能影響到所有業務層的服務。而每個微服務通常有它自己獨立的 Data Store。我們在拆分資料庫時可以適當的做些去正規化化,讓它不需要依賴其他服務的資料。

微服務通常是直接面對使用者的,每個微服務通常直接為使用者提供某個功能。類似的功能可能針對手機有一個服務,針對機頂盒是另外一個服務。在 SOA 設計模式中這種情況通常會用到 Multi-ChannelEndpoint 的模式返回一個大而全的結果兼顧到所有的客戶端的需求。

三 SOA注重自上而下,微服務注重自下而上

SOA 架構在設計開始時會先定義好服務合同。它喜歡集中管理所有的服務,包括集中管理業務邏輯,資料,流程,Schema 等。它使用 Enterprise Inventory 和 Service Composition 等方法來集中管理服務。SOA 架構通常會預先把每個模組服務介面都定義好。模組系統間的通訊必須遵守這些介面,各服務是針對他們的呼叫者。

SOA 架構適用於 TO GAF 之類的架構方法論。

微服務則敏捷得多。只要使用者用得到,就先把這個服務挖出來。然後針對性的,快速確認業務需求,快速開發迭代。

四 總結

微服務與 SOA 有很多相同之處。兩者都屬於典型的、包含鬆耦合分散式元件的系統結構。在圍繞著服務的概念建立架構這一方面,微服務提供了一種更清晰、定義更良好的方式。微服務的原則與敏捷軟體開發思想是高度一致的,而它與 SOA 原則的演化的目標也是相同的,則減少傳統的企業服務匯流排開發的高複雜性。兩者之間最關鍵的區別在於,微服務專注於以自治的方式產生價值。但是兩種架構背後的意圖是不同的:SOA 嘗試將應用整合,一般採用中央管理模式來確保各應用能夠互動運作。微服務嘗試部署新功能,快速有效地擴充套件開發團隊。它著重於分散管理、程式碼再利用與自動化執行。

功能 SOA 微服務
元件大小 大塊業務邏輯 單獨任務或小塊業務邏輯
耦合 通常鬆耦合 總是鬆耦合
公司架構 任何型別 小型、專注於功能交叉的團隊
管理 著重中央管理 著重分散管理
目標 確保應用能夠互動操作 執行新功能,快速拓展開發團隊

微服務並不是一種新思想的方法。它更像是一種思想的精煉,一種 SOA 的精細化演進,並且更好地利用了先進的技術以解決問題,例如容器與自動化等。所以對於我們去選擇服務技術框架時,並不是非黑即白,而是針對 SOA、MSA 兩種架構設計同時要考慮到相容性,對於現有平臺情況架構設計,退則守 SOA,進則攻 MSA,階段性選擇適合的。

一 概述

要實際的應用微服務,需要解決以下問題:

  • 客戶端如何訪問這些服務

  • 每個服務之間如何通訊

  • 如此多的服務,如何實現?

  • 服務掛了,如何解決?(備份方案,應急處理機制)

二 客戶端如何訪問這些服務

原來的 Monolithic 方式開發,所有的服務都是本地的,UI 可以直接呼叫,現在按功能拆分成獨立的服務,跑在獨立的一般都在獨立的虛擬機器上的 Java 程序了。客戶端 UI 如何訪問他?

後臺有 N 個服務,前臺就需要記住管理 N 個服務,一個服務 下線更新升級,前臺就要重新部署,這明顯不服務我們拆分的理念,特別當前臺是移動應用的時候,通常業務變化的節奏更快。

另外,N 個小服務的呼叫也是一個不小的網路開銷。還有一般微服務在系統內部,通常是無狀態的,使用者登入資訊和許可權管理最好有一個統一的地方維護管理(OAuth)。

所以,一般在後臺 N 個服務和 UI 之間一般會一個代理或者叫 API Gateway,他的作用包括:

  • 提供統一服務入口,讓微服務對前臺透明

  • 聚合後臺的服務,節省流量,提升效能

  • 提供安全,過濾,流控等API管理功能

其實這個 API Gateway 可以有很多廣義的實現辦法,可以是一個軟硬一體的盒子,也可以是一個簡單的 MVC 框架,甚至是一個 Node.js 的服務端。他們最重要的作用是為前臺(通常是移動應用)提供後臺服務的聚合,提供一個統一的服務出口,解除他們之間的耦合,不過 API Gateway 也有可能成為 單點故障 點或者效能的瓶頸。

三 每個服務之間如何通訊

所有的微服務都是獨立的 Java 程序跑在獨立的虛擬機器上,所以服務間的通訊就是 IPC(Inter Process Communication),已經有很多成熟的方案。現在基本最通用的有兩種方式:

同步呼叫

  • REST(JAX-RS,Spring Boot)

  • RPC(Thrift, Dubbo)

同步呼叫比較簡單,一致性強,但是容易出調用問題,效能體驗上也會差些,特別是呼叫層次多的時候。一般 REST 基於 HTTP,更容易實現,更容易被接受,服務端實現技術也更靈活些,各個語言都能支援,同時能跨客戶端,對客戶端沒有特殊的要求,只要封裝了 HTTP 的 SDK 就能呼叫,所以相對使用的廣一些。RPC 也有自己的優點,傳輸協議更高效,安全更可控,特別在一個公司內部,如果有統一個的開發規範和統一的服務框架時,他的開發效率優勢更明顯些。就看各自的技術積累實際條件,自己的選擇了。

非同步訊息呼叫

  • Kafka

  • Notify

  • MessageQueue

非同步訊息的方式在分散式系統中有特別廣泛的應用,他既能減低呼叫服務之間的耦合,又能成為呼叫之間的緩衝,確保訊息積壓不會沖垮被呼叫方,同時能保證呼叫方的服務體驗,繼續幹自己該乾的活,不至於被後臺效能拖慢。不過需要付出的代價是一致性的減弱,需要接受資料 最終一致性;還有就是後臺服務一般要實現 冪等性,因為訊息送出於效能的考慮一般會有重複(保證訊息的被收到且僅收到一次對效能是很大的考驗);最後就是必須引入一個獨立的 Broker

四 如此多的服務,如何實現?

在微服務架構中,一般每一個服務都是有多個拷貝,來做負載均衡。一個服務隨時可能下線,也可能應對臨時訪問壓力增加新的服務節點。服務之間如何相互感知?服務如何管理?

這就是服務發現的問題了。一般有兩類做法,也各有優缺點。基本都是通過 Zookeeper 等類似技術做服務註冊資訊的分散式管理。當服務上線時,服務提供者將自己的服務資訊註冊到 ZK(或類似框架),並通過心跳維持長連結,實時更新連結資訊。服務呼叫者通過 ZK 定址,根據可定製演算法,找到一個服務,還可以將服務資訊快取在本地以提高效能。當服務下線時,ZK 會發通知給服務客戶端。

基於客戶端的服務註冊與發現

優點是架構簡單,擴充套件靈活,只對服務註冊器依賴。缺點是客戶端要維護所有呼叫服務的地址,有技術難度,一般大公司都有成熟的內部框架支援,比如 Dubbo。

基於服務端的服務註冊與發現

優點是簡單,所有服務對於前臺呼叫方透明,一般在小公司在雲服務上部署的應用採用的比較多。

五 服務掛了,如何解決?

前面提到,Monolithic 方式開發一個很大的風險是,把所有雞蛋放在一個籃子裡,一榮俱榮,一損俱損。而分散式最大的特性就是網路是不可靠的。通過微服務拆分能降低這個風險,不過如果沒有特別的保障,結局肯定是噩夢。所以當我們的系統是由一系列的服務呼叫鏈組成的時候,我們必須確保任一環節出問題都不至於影響整體鏈路。相應的手段有很多:

  • 重試機制

  • 限流

  • 熔斷機制

  • 負載均衡

  • 降級(本地快取)

# 重試
超時時間的配置是為了保護服務,避免consumer服務因為provider 響應慢而也變得響應很慢,這樣consumer可以儘量保持原有的效能。
但是也有可能provider只是偶爾抖動,那麼超時後直接放棄,不做後續處理,就會導致當前請求錯誤,也會帶來業務方面的損失。
那麼,對於這種偶爾抖動,可以在超時後重試一下,重試如果正常返回了,那麼這次請求就被挽救了,能夠正常給前端返回資料,只不過比原來響應慢一點。
重試時的一些細化策略:
重試可以考慮切換一臺機器來進行呼叫,因為原來機器可能由於臨時負載高而效能下降,重試會更加劇其效能問題,而換一臺機器,得到更快返回的概率也更大一些
# 限流
只允許系統能夠承受的訪問量進來,超出的會被丟棄。降級從系統功能優先順序角度考慮如何應對故障,而限流則從使用者訪問壓力的角度來考慮如何應對故障。
演算法:
漏桶演算法:漏桶演算法思路很簡單,水(請求)先進入到漏桶裡,漏桶以一定的速度出水,當水流入速度過大會直接溢位,可以看出漏桶演算法能強行限制資料的傳輸速率。

令牌桶演算法:對於很多應用場景來說,除了要求能夠限制資料的平均傳輸速率外,還要求允許某種程度的突發傳輸。這時候漏桶演算法可能就不合適了,令牌桶演算法更為適合。
令牌桶演算法的原理是系統會以一個恆定的速度往桶裡放入令牌,而如果請求需要被處理,則需要先從桶裡獲取一個令牌,當桶裡沒有令牌可取時,則拒絕服務。
# 熔斷機制:
當這個介面不可用了,然後下次掉服務的時候就不會再訪問到這個節點了,然後後臺還有一個程式,去實時監控這個服務節點,等他好了,你又可以訪問了。簡單理解就是——比方說排隊買票,有3個視窗,其中一個視窗與排了很多人,然後那個售票員有事走開了,那群人不可能一直等,就去別的視窗買了,然後那個售票員回來了,會通知買票的人,這裡可以買票了。

# 降級:
簡單理解就是——比方說返回很多人再買票,還有人在問路,或者在諮詢問題,那些問路的,諮詢問題的就不處理了,只處理買票

一 什麼是 RPC?

RPC 是指遠端過程呼叫,也就是說兩臺伺服器 A,B 一個應用部署在 A 伺服器上,想要呼叫 B 伺服器上應用提供的函式或方法,由於不在一個記憶體空間,不能直接呼叫,需要通過網路來表達呼叫的語義和傳達呼叫的資料。

二 RPC 是如何通訊的?

  1. 要解決通訊的問題,主要是通過在客戶端和伺服器之間建立 TCP 連線,遠端過程呼叫的所有交換的資料都在這個連線裡傳輸。連線可以是按需連線,呼叫結束後就斷掉,也可以是長連線,多個遠端過程呼叫共享同一個連線。

  2. 要解決定址的問題,也就是說,A 伺服器上的應用怎麼告訴底層的 RPC 框架,如何連線到 B 伺服器(如主機或 IP 地址)以及特定的埠,方法的名稱是什麼,這樣才能完成呼叫。比如基於 Web 服務協議棧的 RPC,就要提供一個 endpoint URI,或者是從 UDDI 服務上查詢。如果是 RMI 呼叫的話,還需要一個 RMI Registry 來註冊服務的地址。

  3. 當 A 伺服器上的應用發起遠端過程呼叫時,方法的引數需要通過底層的網路協議如 TCP 傳遞到 B 伺服器,由於網路協議是基於二進位制的,記憶體中的引數的值要序列化成二進位制的形式,也就是序列化(Serialize)或編組(marshal),通過定址和傳輸將序列化的二進位制傳送給 B 伺服器。

  4. B 伺服器收到請求後,需要對引數進行反序列化(序列化的逆操作),恢復為記憶體中的表達方式,然後找到對應的方法(定址的一部分)進行本地呼叫,然後得到返回值。

  5. 返回值還要傳送回伺服器 A 上的應用,也要經過序列化的方式傳送,伺服器 A 接到後,再反序列化,恢復為記憶體中的表達方式,交給 A 伺服器上的應用。

三 為什麼要用 RPC?

就是無法在一個程序內,甚至一個計算機內通過本地呼叫的方式完成的需求,比如比如不同的系統間的通訊,甚至不同的組織間的通訊。由於計算能力需要橫向擴充套件,需要在多臺機器組成的叢集上部署應用

四 常見RPC框架

功能 Hessian Montan rpcx gRPC Thrift Dubbo Dubbox Spring Cloud
開發語言 跨語言 Java Go 跨語言 跨語言 Java Java Java
分散式(服務治理) × × ×
多序列化框架支援 hessian √(支援Hessian2、Json,可擴充套件) × 只支援protobuf) ×(thrift格式)
多種註冊中心 × × ×
管理中心 × × ×
跨程式語言 ×(支援php client和C server) × × × ×
支援REST × × × × × ×
關注度
上手難度
運維成本
開源機構 Caucho Weibo Apache Google Apache Alibaba Dangdang Apache

實際場景中的選擇

# Spring Cloud : Spring全家桶,用起來很舒服,只有你想不到,沒有它做不到。可惜因為釋出的比較晚,國內還沒出現比較成功的案例,大部分都是試水,不過畢竟有Spring作背書,還是比較看好。
# Dubbox: 相對於Dubbo支援了REST,估計是很多公司選擇Dubbox的一個重要原因之一,但如果使用Dubbo的RPC呼叫方式,服務間仍然會存在API強依賴,各有利弊,懂的取捨吧。
# Thrift: 如果你比較高冷,完全可以基於Thrift自己搞一套抽象的自定義框架吧。
# Montan: 可能因為出來的比較晚,目前除了新浪微博16年初發布的,
# Hessian: 如果是初創公司或系統數量還沒有超過5個,推薦選擇這個,畢竟在開發速度、運維成本、上手難度等都是比較輕量、簡單的,即使在以後遷移至SOA,也是無縫遷移。
# rpcx/gRPC: 在服務沒有出現嚴重效能的問題下,或技術棧沒有變更的情況下,可能一直不會引入,即使引入也只是小部分模組優化使用。

一 CAP 定理

2000 年 7 月,加州大學伯克利分校的 Eric Brewer 教授在 ACM PODC 會議上提出 CAP 猜想。2年後,麻省理工學院的 Seth Gilbert 和 Nancy Lynch 從理論上證明了 CAP。之後,CAP 理論正式成為分散式計算領域的公認定理。

CAP 理論為:一個分散式系統最多隻能同時滿足一致性(Consistency)、可用性(Availability)和分割槽容錯性(Partition tolerance)這三項中的兩項。

1.1 一致性(Consistency)

一致性指 “all nodes see the same data at the same time”,即更新操作成功並返回客戶端完成後,所有節點在同一時間的資料完全一致。

1.2 可用性(Availability)

可用性指“Reads and writes always succeed”,即服務一直可用,而且是正常響應時間。

1.3 分割槽容錯性(Partition tolerance)

分割槽容錯性指“the system continues to operate despite arbitrary message loss or failure of part of the system”,即分散式系統在遇到某節點或網路分割槽故障的時候,仍然能夠對外提供滿足一致性和可用性的服務。

二 CAP 權衡

通過 CAP 理論,我們知道無法同時滿足一致性、可用性和分割槽容錯性這三個特性,那要捨棄哪個呢?

對於多數大型網際網路應用的場景,主機眾多、部署分散,而且現在的叢集規模越來越大,所以節點故障、網路故障是常態,而且要保證服務可用性達到 N 個 9,即保證 P 和 A,捨棄C(退而求其次保證最終一致性)。雖然某些地方會影響客戶體驗,但沒達到造成使用者流程的嚴重程度。

對於涉及到錢財這樣不能有一絲讓步的場景,C 必須保證。網路發生故障寧可停止服務,這是保證 CA,捨棄 P。貌似這幾年國內銀行業發生了不下 10 起事故,但影響面不大,報到也不多,廣大群眾知道的少。還有一種是保證 CP,捨棄 A。例如網路故障是隻讀不寫。

孰優孰略,沒有定論,只能根據場景定奪,適合的才是最好的。

三 BASE 理論

eBay 的架構師 Dan Pritchett 源於對大規模分散式系統的實踐總結,在 ACM 上發表文章提出 BASE 理論,BASE 理論是對 CAP 理論的延伸,核心思想是即使無法做到強一致性(Strong Consistency,CAP 的一致性就是強一致性),但應用可以採用適合的方式達到最終一致性(Eventual Consitency)。

3.1 基本可用(Basically Available)

基本可用是指分散式系統在出現故障的時候,允許損失部分可用性,即保證核心可用。

電商大促時,為了應對訪問量激增,部分使用者可能會被引導到降級頁面,服務層也可能只提供降級服務。這就是損失部分可用性的體現。

3.2 軟狀態(Soft State)

軟狀態是指允許系統存在中間狀態,而該中間狀態不會影響系統整體可用性。分散式儲存中一般一份資料至少會有三個副本,允許不同節點間副本同步的延時就是軟狀態的體現。mysql replication 的非同步複製也是一種體現。

3.3 最終一致性(Eventual Consistency)

最終一致性是指系統中的所有資料副本經過一定時間後,最終能夠達到一致的狀態。弱一致性和強一致性相反,最終一致性是弱一致性的一種特殊情況。

四 ACID 和 BASE 的區別與聯絡

ACID 是傳統資料庫常用的設計理念,追求強一致性模型。BASE 支援的是大型分散式系統,提出通過犧牲強一致性獲得高可用性。

ACID 和 BASE 代表了兩種截然相反的設計哲學,在分散式系統設計的場景中,系統元件對一致性要求是不同的,因此 ACID 和 BASE 又會結合使用。