微服務概念介紹

概述

微服務micro service是和單體應用相對應的一個概念。我們不妨先來回顧單體應用程序是怎樣的一種行爲。在微服務提出之前,世界上流行的應用程序大多都是單體應用程序。何爲單體應用程序,個人認爲其實這更多的是從服務端應用程序架構角度的一個概念。

單體應用程序意味着所有的代碼都是在一個項目當中的,這些代碼是統一打包部署發佈出去的,在一個進程當中運行。

微服務,可以理解爲將原來單體應用中的不同模塊劃分成不同的相對更小的應用程序。解耦合,模塊化在此時發生。 

本質上就是一種分而治之的思想。從思想層面來說並沒有任何全新的東西。當應用程序越來越複雜,可以說這是一條必經之路。即便是單體應用程序,在整個應用程序內部,不同的功能模塊,也是放在不同的包當中的,相關的邏輯也是組織在一起的。

只是微服務將這些模塊幾乎完全的隔離開了,不僅這些代碼分開了,他們的打包,部署,運維,測試甚至數據庫都是隔離的。這些微服務之間的交互就通過彼此暴露的api進行。

什麼是微服務

微服務也被稱爲微服務架構,是一種可將應用程序構造爲一組服務的架構方式,這些服務的特點是:

  • 高度可維護和可測試
  • 松耦合
  • 可獨立部署
  • 圍繞業務模塊進行組織
  • 由一個小團隊擁有

微服務的優劣

微服務的優點和缺點和它的特點以及架構方式密不可分。微服務帶來的好處非常多,主要包含:

  1. 從需求角度來說:每個微服務都很小,這樣能聚焦一個指定的業務功能或業務需求
  2. 從團隊管理的角度來說:微服務能夠被小團隊單獨開發。因此團隊更好管理,可以採用敏捷開發的模式。
  3. 從部署和開發角度來說:微服務是松耦合的,無論是在開發階段或部署階段都是獨立的。單個服務代碼量不會很多,開發啓動起來就會很快。維護成本也更低。此外由於工程量小,這也消除了對技術棧的長期承諾。 開發新服務時,可以選擇新技術堆棧。 同樣,當對現有服務進行重大更改時,您可以使用新技術堆棧將其重寫。
  4. 從技術選擇角度來說:微服務允許選用技術十分靈活,整個項目無需強制要求使用一樣的技術棧。
  5. 從測試角度來說:由於代碼相對較少,因此微服務可以進行較快的單元測試和api測試,這樣利於實現CI持續集成和CD持續交付。

微服務架構模式具有許多重要的好處。首先,它解決了複雜性問題。它將原本是巨大的整體應用程序分解爲一組服務。雖然功能總數不變,但該應用程序已分爲可管理的塊或服務。每個服務都有以RPC或消息驅動的API形式定義的邊界。微服務架構模式強制執行一定程度的模塊化,實際上,使用單一代碼庫很難實現。因此,單個服務的開發速度更快,並且更易於理解和維護。

其次,該體系結構使每個服務可以由專注於該服務的團隊獨立開發。開發人員可以自由選擇任何有意義的技術,只要該服務遵守API合同即可。當然,大多數組織都希望避免完全無政府狀態並限制技術選擇。但是,這種自由意味着開發人員不再有義務使用新項目開始時已經存在的可能過時的技術。編寫新服務時,他們可以選擇使用當前技術。此外,由於服務相對較小,因此使用當前技術重寫舊服務變得可行。

第三,微服務架構模式使每個微服務可以獨立部署。開發人員無需協調其服務本地更改的部署。這些更改只要經過測試就可以部署。 UI團隊可以例如執行A / B測試並快速迭代UI更改。微服務架構模式使連續部署成爲可能。

最後,微服務架構模式使每個服務都可以獨立擴展。您可以僅部署滿足其容量和可用性約束的每個服務的實例數。此外,您可以使用最符合服務資源要求的硬件。例如,您可以在EC2 Compute Optimized實例上部署CPU密集型圖像處理服務,並在EC2 Memory Optimized實例上部署內存數據庫服務。

 

缺點則有:

  1. 部署維護要求比較高:單體應用就一個war包,微服務在一個系統中會有很多的服務,每個服務都對應一個包,維護起來就會複雜一些。在實際環境中,部署和管理由許多不同服務組成的系統也存在操作複雜性
  2. 技術複雜性提高:微服務就會帶來一系列的問題,事務問題,Session一致性問題,鎖問題,分佈式複雜性等。同時雖然單個微服務的測試更加方便,但是應用程序整體的測試以及應用程序相互之間依賴的測試就更加難。contract約定測試在這方面可以提供幫助。此外,還有下面這些技術上的問題:
    • 開發人員必須實現服務間通信機制並處理部分故障
    • 實施跨多個服務的請求更加困難
    • 測試服務之間的交互更加困難
    • 實施跨多個服務的請求需要團隊之間的仔細協調(更高的維護成本)
    • 開發人員工具/ IDE面向構建整體應用程序,不爲開發分佈式應用程序提供明確支持。
  3. 增加內存消耗。微服務架構用N x M服務實例替換了N個整體應用程序實例。如果每個服務都在其自己的JVM中運行(這通常是隔離實例所必需的),則JVM運行時的開銷是M倍。此外,如果每個服務都在自己的VM上運行,就像Netflix一樣,則開銷會更高。

像其他所有技術一樣,微服務架構也有缺點。缺點之一是名稱本身。微服務一詞過分強調服務規模。實際上,有些開發人員主張構建極細粒度的10-100 LOC服務。小型服務雖然更可取,但重要的是要記住,它們是達到目的的一種手段,而不是主要目標。微服務的目標是充分分解應用程序,以促進敏捷應用程序的開發和部署。

微服務的另一個主要缺點是由於微服務應用程序是分佈式系統這一事實而導致的複雜性。開發人員需要選擇並實現基於消息傳遞或RPC的進程間通信機制。此外,由於請求的目的地可能很慢或不可用,它們還必須編寫代碼來處理部分失敗。儘管這都不是火箭科學,但是它比單片應用程序複雜得多,在單片應用程序中,模塊通過語言級方法/過程調用相互調用。

微服務的另一個挑戰是分區數據庫體系結構。更新多個業務實體的業務交易相當普遍。由於只有一個數據庫,因此在單一應用程序中實現這類事務很簡單。但是,在基於微服務的應用程序中,您需要更新不同服務擁有的多個數據庫。通常,不僅由於CAP定理,也不選擇使用分佈式事務。當今許多高度可擴展的NoSQL數據庫和消息傳遞代理完全不支持它們。您最終不得不使用最終的基於一致性的方法,這對開發人員而言更具挑戰性。

測試微服務應用程序也要複雜得多。例如,對於像Spring Boot這樣的現代框架,編寫一個測試類來啓動一個整體Web應用程序並測試其REST API是很簡單的。相反,針對服務的類似測試類將需要啓動該服務及其依賴的任何服務(或至少爲這些服務配置存根)。再一次,這不是火箭科學,但重要的是不要低估這樣做的複雜性。

微服務架構模式的另一個主要挑戰是實現跨多個服務的更改。例如,假設您正在實現一個需要更改服務A,B和C的案例,其中A依賴於B,B依賴於C。在單片應用程序中,您只需更改相應的模塊,集成更改,一口氣部署它們。相反,在微服務架構模式中,您需要仔細計劃和協調對每個服務的更改的推出。例如,您需要先更新服務C,然後再更新服務B,最後再更新服務A。幸運的是,大多數更改通常隻影響一項服務,而需要協調的多服務更改相對較少。

部署基於微服務的應用程序也要複雜得多。單一應用程序可以簡單地部署在傳統負載均衡器後面的一組相同服務器上。每個應用程序實例都配置有基礎結構服務(例如數據庫和消息代理)的位置(主機和端口)。相反,微服務應用程序通常包含大量服務。例如,根據Adrian Cockcroft [編輯– Hailo被MyTaxi收購],Hailo有160種不同的服務,而Netflix有600多種。每個服務將具有多個運行時實例。還有許多需要配置,部署,擴展和監視的活動部件。另外,您還需要實現服務發現機制(在後面的文章中討論),該服務使服務能夠發現其需要與之通信的任何其他服務的位置(主機和端口)。傳統的基於故障單和手動操作的方法無法擴展到這種複雜程度。因此,成功部署微服務應用程序需要開發人員更好地控制部署方法以及高度自動化。

一種自動化方法是使用現成的PaaS,例如Cloud Foundry。 PaaS爲開發人員提供了一種輕鬆的方法來部署和管理其微服務。它使他們免受諸如採購和配置IT資源之類的問題的困擾。同時,配置PaaS的系統和網絡專業人員可以確保遵守最佳做法和公司政策。自動化微服務部署的另一種方法是開發本質上屬於您自己的PaaS。一個典型的起點是將羣集解決方案(例如Kubernetes)與Docker等技術結合使用。

 

在微服務概念被提出之前,人們習慣於開發單體應用程序。因此爲與微服務進行對比,我們不妨來試着構建一個單體應用程序。下面我們通過Nginx官網的介紹來看一下microservice和單體應用程序

構建單體應用程序Monolithic Application

假設我們要構建一個全新的出租車叫車應用程序,旨在與Uber和Hailo競爭。 在進行一些初步的會議和需求收集之後,我們可以手動創建一個新項目,也可以使用Rails,Spring Boot,Play或Maven附帶的生成器來創建一個新項目。 此新應用程序將具有模塊化的六角形體系結構,如下圖所示:

Modular, but still monolithic, architecture used as basis for sample microservices application

應用程序的核心是業務邏輯,該業務邏輯由service,domain object和event等模塊實現。圍繞中間核心的是與外部世界接口的適配器adapters。適配器的示例包括數據庫訪問組件,生成和使用消息的消息傳遞組件以及公開API或實現UI的Web組件。

儘管具有邏輯模塊化的體系結構,但該應用程序卻作爲一個整體打包和部署。實際的打包格式取決於應用程序的語言和框架。例如,許多Java應用程序打包爲WAR文件,並部署在諸如Tomcat或Jetty之類的應用程序服務器上。其他也有一些Java應用程序打包爲獨立的可執行JAR。同樣,Rails和Node.js應用程序打包爲目錄層次結構。

用這種風格編寫的應用程序非常普遍。由於我們的IDE和其他工具專注於構建單個應用程序,因此它們易於開發。這些類型的應用程序也易於測試。您可以通過簡單地啓動應用程序並使用Selenium測試UI來實施端到端測試。整體應用程序也易於部署。只需要將打包的應用程序複製到服務器即可。您還可以通過在負載平衡器後面運行多個副本來擴展應用程序。在項目的早期階段,它運作良好。

單體應用程序的地獄

但是,這種簡單的方法有很大的侷限性。會取得成功的應用程序具有隨着時間的流逝變得越來越龐大的趨勢。在每次需要完成一些業績的時期,開發團隊都會開發更多的功能,這就意味着要添加許多行代碼。幾年後,您的小型,簡單應用程序將成長爲巨大的整體。舉一個極端的例子,我最近採訪了一位開發人員,他正在編寫一種工具來分析其數百萬行代碼(LOC)應用程序中數千個JAR之間的依賴關係。我敢肯定,經過多年的開發,衆多的開發人員共同努力創造了這種mosnster一樣的應用程序。(以博主的親身經歷來看,博主曾在公司做過一個項目歷史長達15年以上,代碼多達400萬行以上的單體應用程序,當客戶變多的時候會出現許多問題)

一旦您的應用程序變成了一個龐大,複雜的整體,您的開發組織就可能陷入困境。進行敏捷開發和交付的任何嘗試都會失敗。一個主要問題是應用程序極其複雜。對於任何一個開發人員來說,它太大了,根本無法完全理解。結果,修復錯誤和正確實現新功能變得困難且耗時。而且,這往往是螺旋式下降。如果代碼庫難以理解,則將無法正確進行更改。最後,您將得到一個巨大的,難以理解的大泥球。

應用程序的絕對大小也會減慢開發速度。應用程序越大,啓動時間越長(同樣深有體會)。例如,在最近的一項調查中,一些開發人員報告啓動時間長達12分鐘。我還聽說了一些需要花費40分鐘才能啓動的應用程序的軼事。如果開發人員必須定期重新啓動應用程序服務器,那麼他們一整天的時間都將花在等待周圍,從而降低他們的生產力。

大型,複雜的整體應用程序的另一個問題是,會帶來持續部署(CD)的障礙。如今,SaaS應用程序的最新技術是每天將變更推送到生產中多次。對於複雜的整體而言,這極其困難,因爲您必須重新部署整個應用程序才能更新其中的任何一部分。我前面提到的漫長的啓動時間也無濟於事。另外,由於通常不會很好地瞭解更改的影響,因此您可能必須進行大量的手動測試。因此,幾乎不可能進行連續部署。

當不同的模塊具有衝突的資源需求時,單體應用程序也可能難以擴展。例如,一個模塊可能實現CPU密集型圖像處理邏輯,並且理想情況下將部署在Amazon EC2 Compute Optimized實例中。另一個模塊可能是內存數據庫,最適合EC2內存優化的實例。但是,由於這些模塊是一起部署的,因此您必須在硬件選擇上進行折中。

整體應用的另一個問題是可靠性。由於所有模塊都在同一個進程中運行,因此任何模塊中的錯誤(例如內存泄漏)都可能導致整個進程中斷。而且,由於該應用程序的所有實例都是相同的,因此該錯誤將影響整個應用程序的可用性。

最後但並非最不重要的一點是,單片應用程序使採用新框架和語言變得極爲困難。例如,假設您有200萬行使用XYZ框架編寫的代碼。重寫整個應用程序以使用較新的ABC框架將非常昂貴(無論是時間還是成本),即使該框架要好得多。結果,採用新技術存在巨大的障礙。在項目開始時,您會遇到各種技術選擇,而您會陷入困境。

總結一下:您有一個成功的業務關鍵型應用程序,已經成長爲開發人員無法理解的龐然大物。它是使用過時的,非生產性的技術編寫的,這使得僱用有才能的開發人員很困難。該應用程序難以擴展且不可靠。結果就是,不可能進行敏捷的開發和交付。

微服務–解決複雜性

許多組織,例如Amazon,eBay和Netflix,都採用了現在稱爲微服務架構的模式來解決此問題。 與其構建一個單一的,單體應用程序,不如將應用程序拆分爲一組較小的,相互連接的服務。

服務通常實現一組不同的特徵或功能,例如訂單管理,客戶管理等。每個微服務都是一個微型應用程序,具有自己的六邊形體系結構,該體系結構由業務邏輯和各種adapter組成。 某些微服務會暴露其他微服務或應用程序客戶端需要使用的API。 其他微服務可能實現Web UI。 在運行時,每個實例通常是雲VM或Docker容器。

例如,下圖顯示了先前描述的叫車系統的可能分解。

現在,應用程序的每個功能區域都由其自己的微服務實現。此外,該Web應用程序被分爲一組簡單的Web應用程序(例如,在我們的出租車叫車示例中,一個用於乘客,一個用於駕駛員)。這使得爲​​特定用戶,設備或特殊用例部署不同的體驗變得更加容易。

每個後端服務公開一套REST API,大多數服務使用其他服務提供的API。例如,駕駛員管理使用通知服務器來通知可用的駕駛員潛在的行程。 UI服務調用其他服務以呈現網頁。服務還可以使用基於消息機制的異步通信。

某些REST API也公開給駕駛員和乘客使用的移動應用程序。但是,這些應用無法直接訪問後端服務。相反,通信是通過稱爲API網關API gateway的中介進行的。 API gateway負責負載平衡,緩存,訪問控制,API計量和monitor等任務,並且可以使用NGINX有效地實現。

 

在運行時,行程管理服務由多個服務實例組成。每個服務實例都是一個Docker容器。爲了實現高度可用,這些容器在多個Cloud VM上運行。服務實例的前面是一個負載均衡器,例如NGINX,它在實例之間分配請求。負載平衡器還可能處理其他問題,例如緩存,訪問控制,API計量和監視。

微服務架構模式極大地影響了應用程序與數據庫之間的關係。每個服務都具有自己的數據庫架構,而不是與其他服務共享單個數據庫架構。一方面,這種方法與企業範圍的數據模型的思想相矛盾。而且,它通常會導致某些數據重複。但是,如果您想從微服務中受益,則每個服務都具有數據庫架構是必不可少的,因爲這樣可以確保鬆散耦合。下圖顯示了示例應用程序的數據庫體系結構。

Database architecture in sample microservices application for ride service

每個服務都有其自己的數據庫。此外,服務可以使用最適合其需求的一種數據庫,即多語言持久性體系結構。例如,“駕駛員管理”(該駕駛員發現與潛在乘客接近的駕駛員)必須使用支持有效地理位置查詢的數據庫。

從表面上看,微服務架構模式類似於SOA。使用這兩種方法,體系結構都由一組服務組成。但是,考慮微服務架構模式的一種方法是,它無需商業化和可察覺的Web服務規範(WS‑ *)和企業服務總線(ESB)的SOA。基於微服務的應用程序傾向於使用諸如REST之類的更簡單,輕便的協議,而不是WS- *。他們還非常避免使用ESB,而是在微服務本身中實現類似於ESB的功能。微服務架構模式還拒絕了SOA的其他部分,例如規範架構的概念。

 

怎麼解決微服務的問題?

對於devops的問題:

這要求相關人員必須具備devops的能力。所謂devops,就是打包,部署,運行,監控我們的微服務等工作。爲什麼微服務需要強調這些問題,因爲相對於單體應用只需要打包部署單個包而言,對於每個拆分後的微服務進行編譯、打包、部署必將是原來工作量的數倍,如果不採用自動化工具,這些工作將會消耗大量的時間和精力也做不好,從這個角度來說,使用自動化工具是必須的。

並且由於多個微服務採用框架各異,那麼微服務部署所依賴的基礎環境,必將異常複雜繁瑣。

可以說DevOps是微服務實施的充分必要條件

對於事務一致性問題,首先必須提出的一點是:你的需求裏到底需不需要事務一致性?如果沒有,這個問題就不需要考慮。如果有,這個問題才存在。

微服務中的事務一致性問題可能會面臨下面這些調整:

首先,對於微服務架構來說,數據訪問更加複雜,數據庫是微服務私有的,唯一可訪問的方式就是通過該微服務的API。這種數據訪問方式的好處是使得微服務之間松耦合,並且彼此之間獨立非常容易進行性能擴展。

其次,不同的微服務經常使用不同的數據庫。應用會產生各種不同類型的數據,關係型數據庫並不一定是最佳選擇。例如,某個產生和查詢字符串的應用採用Elasticsearch的字符搜索引擎;某個產生社交圖片數據的應用可以採用圖數據庫,例如,Neo4j;基於微服務的應用一般都使用SQL和NoSQL結合的模式。但是這些非關係型數據大多數並不支持事務。可見在微服務架構中已經不能選擇分佈式事務了。

依據CAP理論,必須在可用性(availability)和一致性(consistency)之間做出選擇。如果選擇提供一致性需要付出在滿足一致性之前阻塞其他併發訪問的代價。這可能持續一個不確定的時間,尤其是在系統已經表現出高延遲時或者網絡故障導致失去連接時。

依據目前的成功經驗,可用性一般是更好的選擇,但是在服務和數據庫之間維護數據一致性是非常根本的需求,因此微服務架構中應選擇滿足最終一致性。

目前使用比較多的方案是
結合MQ消息中間件實現的可靠消息最終一致性。可靠消息最終一致性,需要業務系統結合MQ消息中間件實現,在實現過程中需要保證消息的成功發送及成功消費。即需要通過業務系統控制MQ的消息狀態。

關於微服務的事務問題,更詳細的內容暫時可以參考這篇博客:微服務架構下的事務一致性保證

總結

構建複雜的應用程序本質上是一件困難的事情。 單體架構僅對簡單,輕量級的應用有意義。 如果將其用於複雜的應用程序,將陷入痛苦的世界。 儘管存在缺點和實現挑戰,但微服務架構模式是複雜,不斷髮展的應用程序的更好選擇。

總的來說,對於任何一種技術而言都不是絕對盲目推崇的,適合的才最好,微服務自然有很多好處,但是在實際的項目中依然需要結合實際需求和情況進行實踐。但是總的來說,軟件項目的趨勢是在朝這個方向前進的。越來越多的公司和項目都在採用這種架構模式了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章