c# 微服务学习_资深架构师学习笔记:什么是微服务?
們先來看看為什么要考慮使用微服務(wù)。
構(gòu)建單體應(yīng)用
我們假設(shè),您開始開發(fā)一個(gè)打車應(yīng)用,打算與 Uber 和 Hailo 競(jìng)爭(zhēng)。經(jīng)過初步交流和需求收集,您開始手動(dòng)或者使用類似 Rails、Spring Boot、Play 或者 Maven 等平臺(tái)來生成一個(gè)新項(xiàng)目。
該新應(yīng)用是一個(gè)模塊化的六邊形架構(gòu),如圖 1-1 所示:
圖 1-1、一個(gè)簡(jiǎn)單的打車應(yīng)用
該應(yīng)用的核心是由模塊實(shí)現(xiàn)的業(yè)務(wù)邏輯,它定義了服務(wù)、領(lǐng)域?qū)ο蠛褪录?。圍繞核心的是與外部世界接口對(duì)接的適配器。適配器示例包括數(shù)據(jù)庫(kù)訪問組件、生產(chǎn)和消費(fèi)消息的消息組件和暴露了 API 或?qū)崿F(xiàn)了一個(gè) UI 的 web 組件。
盡管有一個(gè)邏輯模塊化架構(gòu),但應(yīng)用程序被作為一個(gè)單體進(jìn)行打包和部署。實(shí)際格式取決于應(yīng)用程序的語(yǔ)言和框架。例如,許多 Java 應(yīng)用程序被打包成 WAR 文件部署在如 Tomcat 或者 Jetty 之類的應(yīng)用服務(wù)器上。其他 Java 應(yīng)用程序被打包成自包含(self-contained)的可執(zhí)行 JAR。類似地,Rails 和 Node.js 應(yīng)用程序被打包為有目錄層次的結(jié)構(gòu)。
以這種風(fēng)格編寫的應(yīng)用是很常見的。他們很容易開發(fā),因?yàn)槲覀兊?IDE 和其他工具就是專注于構(gòu)建單體應(yīng)用。這些應(yīng)用程序也很容易測(cè)試,您可以通過簡(jiǎn)單地啟動(dòng)并使用如 Selenium 測(cè)試包來測(cè)試 UI 以輕松地實(shí)現(xiàn)端到端(end-to-end)測(cè)試。單體應(yīng)用同樣易于部署,你只需拷貝打包好的應(yīng)用程序到服務(wù)器上。您還可以通過運(yùn)行多個(gè)副本和結(jié)合負(fù)載均衡器來擴(kuò)展應(yīng)用。在項(xiàng)目的早期階段,它可以良好運(yùn)作。
走向單體地獄
不幸的是,這種簡(jiǎn)單的方法有很大的局限性。成功的應(yīng)用有一個(gè)趨勢(shì),隨著時(shí)間推移而變得越來越臃腫。您的開發(fā)團(tuán)隊(duì)在每個(gè)沖刺階段都要實(shí)現(xiàn)更多的用戶需求,這意味著需要添加許多行代碼。幾年之后,小而簡(jiǎn)單的應(yīng)用將會(huì)逐漸成長(zhǎng)成一個(gè)龐大的單體。為了給出一個(gè)極端示例,我最近和一位開發(fā)者做了交談,他正在編寫一個(gè)工具,該工具用于從他們的數(shù)百萬行代碼(lines of code,LOC)應(yīng)用中分析出數(shù)千個(gè) JAR 之間的依賴。我相信這是大量開發(fā)者在多年齊心協(xié)力下創(chuàng)造出了這樣的野獸。
一旦您的應(yīng)用程序成為了一個(gè)龐大、復(fù)雜的單體,您的開發(fā)組織可能會(huì)陷入了一個(gè)痛苦的境地,敏捷開發(fā)和交付的任何一次嘗試都將原地徘徊。一個(gè)主要問題是應(yīng)用程序?qū)嵲诜浅?fù)雜,其對(duì)于任何一個(gè)開發(fā)人員來說顯得過于龐大,這是可以理解的。最終,正確修復(fù) bug 和實(shí)現(xiàn)新功能變得非常困難而耗時(shí)。此外,這種趨勢(shì)就像是往下的螺旋。如果基本代碼都令人難以理解,那么改變也不會(huì)變得正確,您最終得到的將是一個(gè)巨大且不可思議的大泥球。
應(yīng)用程序的規(guī)模也將減緩發(fā)展。 應(yīng)用程序越大,啟動(dòng)時(shí)間越長(zhǎng)。 我調(diào)查過開發(fā)者們的單體應(yīng)用的大小和性能,一些報(bào)告的啟動(dòng)時(shí)間為 12 分鐘。我也聽說過應(yīng)用程序啟動(dòng)需要 40 分鐘以上的怪事。如果開發(fā)人員經(jīng)常要重啟應(yīng)用服務(wù)器,那么很大一部分時(shí)間都是在等待中度過,他們的生產(chǎn)力將受到限制。
另一個(gè)大問題是, 復(fù)雜的單體應(yīng)用本身就是持續(xù)部署的障礙 。如今,SaaS 應(yīng)用發(fā)展到了可以每天多次將變更推送到生產(chǎn)環(huán)境。這對(duì)于復(fù)雜的單體來說非常困難,因?yàn)槟枰匦虏渴鹫麄€(gè)應(yīng)用程序才能更新其中任何一部分。聯(lián)想到我之前提到的漫長(zhǎng)啟動(dòng)時(shí)間,這也不會(huì)是什么好事。此外,因變更所產(chǎn)生的影響通常不是很明確,您很可能需要做大量的手工測(cè)試。因此,持續(xù)部署是不可能做到的。當(dāng)不同模塊存在資源需求沖突時(shí),單體應(yīng)用可能難以擴(kuò)展。例如,一個(gè)模塊可能會(huì)執(zhí)行 CPU 密集型圖像處理邏輯,理想情況下是部署在 Amazon EC2 Compute Optimized 實(shí)例中。另一個(gè)模塊可能是一個(gè)內(nèi)存數(shù)據(jù)庫(kù),最適合部署到 EC2 Memory-optimized 實(shí)例。然而,由于這些模塊被部署在一起,您必須在硬件選擇上做出妥協(xié)。
單體應(yīng)用的另一個(gè)問題是可靠性。 因?yàn)樗心K都運(yùn)行在同一進(jìn)程中。任何模塊的一個(gè) bug,比如內(nèi)存泄漏,可能會(huì)拖垮整個(gè)進(jìn)程 。此外,由于應(yīng)用程序的所有實(shí)例都是相同的,該錯(cuò)誤將影響到整個(gè)應(yīng)用的可用性。
最后但同樣重要, 單體應(yīng)用使得采用新框架和語(yǔ)言變得非常困難 。例如,我們假設(shè)您有 200 萬行代碼使用了 XYZ 框架編寫。如果使用較新的 ABC 框架來重寫整個(gè)應(yīng)用,這將非常昂貴(在時(shí)間和成本方面),即使框架非常好。因此,這對(duì)于采用新技術(shù)是一個(gè)非常大的障礙。在項(xiàng)目開始時(shí),您無論選擇何種新技術(shù)都會(huì)感到困擾。
總結(jié)一下:您有一個(gè)成功的關(guān)鍵業(yè)務(wù)應(yīng)用程序,它已經(jīng)發(fā)展成為一個(gè)只有少數(shù)開發(fā)人員(如果有的話)能夠理解的巨大單體。它使用了過時(shí)、非生產(chǎn)性技術(shù)編寫,這使得招聘優(yōu)秀開發(fā)人員變得非常困難。應(yīng)用程序變得難以擴(kuò)展,不可靠。因此敏捷開發(fā)和應(yīng)用交付是不可能的。
那么您能做些什么呢?
微服務(wù) — 解決復(fù)雜問題
許多如 Amazon、eBay 和 Netflix 這樣的組織,已經(jīng)采用現(xiàn)在所謂的微服務(wù)架構(gòu)模式解決了這個(gè)問題,而不是構(gòu)建一個(gè)臃腫的單體應(yīng)用。 它的思路是將應(yīng)用程序分解成一套較小的互連服務(wù)。一個(gè)服務(wù)通常實(shí)現(xiàn)了一組不同的特性或功能,例如訂單管理、客戶管理等。每一個(gè)微服務(wù)都是一個(gè)迷你應(yīng)用,它自己的六邊形架構(gòu)包括了業(yè)務(wù)邏輯以及多個(gè)適配器。一些微服務(wù)會(huì)暴露一個(gè)供其他微服務(wù)或應(yīng)用客戶端消費(fèi)的 API。其他微服務(wù)可能實(shí)現(xiàn)了一個(gè) web UI。 在運(yùn)行時(shí),每個(gè)實(shí)例通常是一個(gè)云虛擬機(jī)(virtual machine,VM)或者一個(gè) Docker 容器。例如,前面描述的系統(tǒng)可能分解成如圖 1-2 所示:
圖 1-2、一個(gè)單體應(yīng)用分解成微服務(wù)
應(yīng)用程序的每個(gè)功能區(qū)域現(xiàn)在都由自己的微服務(wù)實(shí)現(xiàn)。此外,Web 應(yīng)用程序被劃分為一組更簡(jiǎn)單的應(yīng)用。例如,以我們的出租車為例,一個(gè)是乘客的應(yīng)用,一個(gè)是司機(jī)的應(yīng)用。這使得它更容易地為特定的用戶、司機(jī)、設(shè)備或者專門的用例部署不同的場(chǎng)景。每個(gè)后端服務(wù)暴露一個(gè) REST API,大部分服務(wù)消費(fèi)的 API 由其他服務(wù)提供。例如,Driver Management 使用了 Notification 服務(wù)器來通知可用司機(jī)一個(gè)可選路程。UI 服務(wù)調(diào)用了其他服務(wù)來渲染頁(yè)面。服務(wù)也可以使用異步、基于消息的通信。本電子書后面將會(huì)更加詳細(xì)介紹服務(wù)間通信。
一些 REST API 也暴露給移動(dòng)端應(yīng)用以供司機(jī)和乘客使用。然而,應(yīng)用不能直接訪問后端服務(wù)。相反,他們之間的通信是由一個(gè)稱為 API 網(wǎng)關(guān)(API Gateway)的中介負(fù)責(zé)。API 網(wǎng)關(guān)負(fù)責(zé)負(fù)載均衡、緩存、訪問控制、API 計(jì)量和監(jiān)控,可以通過使用 NGINX 來實(shí)現(xiàn)。第二章將詳細(xì)討論 API 網(wǎng)關(guān)。
圖 1-3、開發(fā)和交付中的伸縮立方(Scale Cube)
微服務(wù)架構(gòu)模式相當(dāng)于此伸縮立方的 Y 軸坐標(biāo),此立方是一個(gè)來自《架構(gòu)即未來》的三維伸縮模型。另外兩個(gè)坐標(biāo)軸是由運(yùn)行多個(gè)相同應(yīng)用程序副本的負(fù)載均衡器組成的 X 軸坐標(biāo)和 Z 軸坐標(biāo)(或數(shù)據(jù)分區(qū)),其中請(qǐng)求的屬性(例如,一行記錄的主鍵或者客戶標(biāo)識(shí))用于將請(qǐng)求路由到特定的服務(wù)器。應(yīng)用程序通常將這三種類型的坐標(biāo)方式結(jié)合一起使用。Y 軸坐標(biāo)將應(yīng)用分解成微服務(wù),如圖 1-2 所示。
在運(yùn)行時(shí),X 坐標(biāo)軸上運(yùn)行著服務(wù)的多個(gè)實(shí)例,每個(gè)服務(wù)配合負(fù)載均衡器以滿足吞吐量和可用性。某些應(yīng)用程序也有可能使用 Z 坐標(biāo)軸來進(jìn)行分區(qū)服務(wù)。圖 1-4 展示了如何用 Docker 將 Trip Management 服務(wù)部署到 Amazon EC2 上運(yùn)行。
圖 1-4、使用 Docker 部署 Trip Management 服務(wù)
在運(yùn)行時(shí),Trip Management 服務(wù)由多個(gè)服務(wù)實(shí)例組成,每個(gè)服務(wù)實(shí)例是一個(gè) Docker 容器。為了實(shí)現(xiàn)高可用,容器是在多個(gè)云虛擬機(jī)上運(yùn)行的。服務(wù)實(shí)例之前是一個(gè)類似 NGINX 的負(fù)載均衡器,用于跨實(shí)例分發(fā)請(qǐng)求。負(fù)載均衡器也可以處理其他問題,如緩存、訪問控制、API 度量和監(jiān)控。
微服務(wù)架構(gòu)模式明顯影響到了應(yīng)用程序與數(shù)據(jù)庫(kù)之間的關(guān)系,與其他共享單個(gè)數(shù)據(jù)庫(kù)模式(schema)服務(wù)有所不同,其每一個(gè)服務(wù)都有自己的數(shù)據(jù)庫(kù)模式。一方面,這種做法與企業(yè)級(jí)數(shù)據(jù)庫(kù)數(shù)據(jù)模型的想法相背,此外,它經(jīng)常導(dǎo)致部分?jǐn)?shù)據(jù)冗余。然而,如果您想從微服務(wù)中受益,每一個(gè)服務(wù)都應(yīng)該有自己的數(shù)據(jù)庫(kù)模式,因?yàn)樗軐?shí)現(xiàn)松耦合。圖 1-5 展示了數(shù)據(jù)庫(kù)架構(gòu)示例應(yīng)用程序。
每個(gè)服務(wù)都擁有各自的數(shù)據(jù)庫(kù)。而且,服務(wù)可以使用一種最適合其需求、號(hào)稱多語(yǔ)言持久架構(gòu)(polyglot persistence architecture)的數(shù)據(jù)庫(kù)。例如,Driver Management,要找到與潛在乘客接近的司機(jī),就必須使用支持高效地理查詢的數(shù)據(jù)庫(kù)。
圖 1-5、打車應(yīng)用的數(shù)據(jù)庫(kù)架構(gòu)
從表面上看,微服務(wù)架構(gòu)模式類似于 SOA。 微服務(wù)是由一組服務(wù)組成。 然而,換另一種方式去思考微服務(wù)架構(gòu)模式,它是沒有商業(yè)化的 SOA,沒有集成 Web 服務(wù)規(guī)范(WS-*)和企業(yè)服務(wù)總線(Enterprise Service Bus,ESB)。基于微服務(wù)的應(yīng)用支持更簡(jiǎn)單、輕量級(jí)的協(xié)議,例如,REST,而不是 WS-*。他們也盡量避免使用 ESB,而是實(shí)現(xiàn)微服務(wù)本身具有類似 ESB 的功能。微服務(wù)架構(gòu)也拒絕了 SOA 的其他部分,例如,數(shù)據(jù)訪問規(guī)范模式概念。
微服務(wù)的優(yōu)點(diǎn)
微服務(wù)架構(gòu)模式有許多非常好的地方。
第一,它解決了復(fù)雜問題。它把可能會(huì)變得龐大的單體應(yīng)用程序分解成一套服務(wù)。雖然功能數(shù)量不變,但是應(yīng)用程序已經(jīng)被分解成可管理的塊或者服務(wù)。每個(gè)服務(wù)都有一個(gè)明確定義邊界的方式,如遠(yuǎn)程過程調(diào)用(RPC)驅(qū)動(dòng)或消息驅(qū)動(dòng) API。微服務(wù)架構(gòu)模式強(qiáng)制一定程度的模塊化,實(shí)際上,使用單體代碼來實(shí)現(xiàn)是極其困難的。因此,使用微服務(wù)架構(gòu)模式,個(gè)體服務(wù)能被更快地開發(fā),并更容易理解與維護(hù)。
第二,這種架構(gòu)使得每個(gè)服務(wù)都可以由一個(gè)團(tuán)隊(duì)獨(dú)立專注開發(fā)。開發(fā)者可以自由選擇任何符合服務(wù) API 契約的技術(shù)。當(dāng)然,更多的組織是希望通過技術(shù)選型限制來避免完全混亂的狀態(tài)。然而,這種自由意味著開發(fā)人員不再有可能在這種自由的新項(xiàng)目開始時(shí)使用過時(shí)的技術(shù)。當(dāng)編寫一個(gè)新服務(wù)時(shí),他們可以選擇當(dāng)前的技術(shù)。此外,由于服務(wù)較小,使用當(dāng)前技術(shù)重寫舊服務(wù)將變得更加可行。
第三,微服務(wù)架構(gòu)模式可以實(shí)現(xiàn)每個(gè)微服務(wù)獨(dú)立部署。開發(fā)人員根本不需要去協(xié)調(diào)部署本地變更到服務(wù)。這些變更一經(jīng)測(cè)試即可立即部署。比如,UI 團(tuán)隊(duì)可以執(zhí)行 A|B 測(cè)試,并快速迭代 UI 變更。微服務(wù)架構(gòu)模式使得持續(xù)部署成為可能。
最后,微服務(wù)架構(gòu)模式使得每個(gè)服務(wù)能夠獨(dú)立擴(kuò)展。您可以僅部署滿足每個(gè)服務(wù)的容量和可用性約束的實(shí)例數(shù)目。此外,您可以使用與服務(wù)資源要求最匹配的硬件。例如,您可以在 EC2 Compute Optimized 實(shí)例上部署一個(gè) CPU 密集型圖像處理服務(wù),并且在 EC2 Memory-optimized 實(shí)例上部署一個(gè)內(nèi)存數(shù)據(jù)庫(kù)服務(wù)。
微服務(wù)的缺點(diǎn)
就像 Fred Brooks 大約在 30 年前寫的《人月神話》中說的,沒有銀彈。與其他技術(shù)一樣,微服務(wù)架構(gòu)模式也存在著缺點(diǎn)。
其中一個(gè)缺點(diǎn)就是名稱本身。微服務(wù)這個(gè)術(shù)語(yǔ)的重點(diǎn)過多偏向于服務(wù)的規(guī)模。事實(shí)上,有些開發(fā)者主張構(gòu)建極細(xì)粒度的 10 至 100 LOC(代碼行) 服務(wù),雖然這對(duì)于小型服務(wù)可能比較好,但重要的是要記住, 小型服務(wù)只是一種手段,而不是主要目標(biāo) 。微服務(wù)的目標(biāo)在于充分分解應(yīng)用程序以方便應(yīng)用敏捷開發(fā)和部署。
微服務(wù)另一個(gè)主要缺點(diǎn)是由于微服務(wù)是一個(gè)分布式系統(tǒng),其使得整體變得復(fù)雜。開發(fā)者需要選擇和實(shí)現(xiàn)基于消息或者 RPC 的進(jìn)程間通信機(jī)制。此外,由于目標(biāo)請(qǐng)求可能很慢或者不可用,他們必須要編寫代碼來處理局部故障。雖然這些并不是很復(fù)雜、高深,但模塊間通過語(yǔ)言級(jí)方法/過程調(diào)用相互調(diào)用,這比單體應(yīng)用要復(fù)雜得多。
微服務(wù)的另一個(gè)挑戰(zhàn)是分區(qū)數(shù)據(jù)庫(kù)架構(gòu)。更新多個(gè)業(yè)務(wù)實(shí)體的業(yè)務(wù)事務(wù)是相當(dāng)普遍的。這些事務(wù)在單體應(yīng)用中的實(shí)現(xiàn)顯得微不足道,因?yàn)閱误w只存在一個(gè)單獨(dú)的數(shù)據(jù)庫(kù)。在基于微服務(wù)的應(yīng)用程序中,您需要更新不同服務(wù)所用的數(shù)據(jù)庫(kù)。通常不會(huì)選擇分布式事務(wù),不僅僅是因?yàn)?CAP 定理。他們根本不支持如今高度可擴(kuò)展的 NoSQL 數(shù)據(jù)庫(kù)和消息代理。您最后不得不使用基于最終一致性的方法,這對(duì)于開發(fā)人員來說更具挑戰(zhàn)性。
測(cè)試微服務(wù)應(yīng)用程序也很復(fù)雜。例如,使用現(xiàn)代框架如 Spring Boot,只需要編寫一個(gè)測(cè)試類來啟動(dòng)一個(gè)單體 web 應(yīng)用程序并測(cè)試其 REST API。相比之下,一個(gè)類似的測(cè)試類對(duì)于微服務(wù)來說需要啟動(dòng)該服務(wù)及其所依賴的所有服務(wù),或者至少為這些服務(wù)配置存根。再次聲明,雖然這不是一件高深的事情,但不要低估了這樣做的復(fù)雜性。
微服務(wù)架構(gòu)模式的另一個(gè)主要挑戰(zhàn)是實(shí)現(xiàn)了跨越多服務(wù)變更。例如,我們假設(shè)您正在實(shí)現(xiàn)一個(gè)變更服務(wù) A、服務(wù) B 和 服務(wù) C 的需求,其中 A 依賴于 B,且 B 依賴于 C。在單體應(yīng)用程序中,您可以簡(jiǎn)單地修改相應(yīng)的模塊、整合變更并一次性部署他們。相反,在微服務(wù)中您需要仔細(xì)規(guī)劃和協(xié)調(diào)出現(xiàn)的變更至每個(gè)服務(wù)。例如,您需要更新服務(wù) C,然后更新服務(wù) B,最后更新服務(wù) A。幸運(yùn)的是,大多數(shù)變更只會(huì)影響一個(gè)服務(wù),需要協(xié)調(diào)的多服務(wù)變更相對(duì)較少。
部署基于微服務(wù)的應(yīng)用程序也是相當(dāng)復(fù)雜的。一個(gè)單體應(yīng)用可以很容易地部署到基于傳統(tǒng)負(fù)載均衡器的一組相同服務(wù)器上。每個(gè)應(yīng)用程序?qū)嵗寂渲糜谢A(chǔ)設(shè)施服務(wù)的位置(主機(jī)和端口),比如數(shù)據(jù)庫(kù)和消息代理。相比之下,微服務(wù)應(yīng)用程序通常由大量的服務(wù)組成。例如,據(jù) Adrian Cockcroft 了解到,Hailo 擁有 160 個(gè)不同的服務(wù),Netflix 擁有的服務(wù)超過 600 個(gè)。
每個(gè)服務(wù)都有多個(gè)運(yùn)行時(shí)實(shí)例。還有更多的移動(dòng)部件需要配置、部署、擴(kuò)展和監(jiān)控。此外,您還需要實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)機(jī)制,使得服務(wù)能夠發(fā)現(xiàn)需要與之通信的任何其他服務(wù)的位置(主機(jī)和端口)。比較傳統(tǒng)麻煩的基于票據(jù)(ticket-based)和手動(dòng)的操作方式無法擴(kuò)展到如此復(fù)雜程度。因此,要成功部署微服務(wù)應(yīng)用程序,需要求開發(fā)人員能高度控制部署方式和高度自動(dòng)化。
一種自動(dòng)化方式是使用現(xiàn)成的平臺(tái)即服務(wù)(PaaS),如 Cloud Foundry。PaaS 為開發(fā)人員提供了一種簡(jiǎn)單的方式來部署和管理他們的微服務(wù)。它讓開發(fā)人員避開了諸如采購(gòu)和配置 IT 資源等煩惱。同時(shí),配置 PaaS 的系統(tǒng)人員和網(wǎng)絡(luò)專業(yè)人員可以確保達(dá)到最佳實(shí)踐以落實(shí)公司策略。自動(dòng)化微服務(wù)部署的另一個(gè)方式是開發(fā)自己的 PaaS。一個(gè)普遍的起點(diǎn)是使用集群方案,如 Kubernetes,與 Docker 等容器技術(shù)相結(jié)合。
總結(jié)
構(gòu)建復(fù)雜的微服務(wù)應(yīng)用程序本質(zhì)上是困難的。單體架構(gòu)模式只適用于簡(jiǎn)單、輕量級(jí)的應(yīng)用程序,如果您使用它來構(gòu)建復(fù)雜應(yīng)用,您最終會(huì)陷入痛苦的境地。微服務(wù)架構(gòu)模式是復(fù)雜、持續(xù)發(fā)展應(yīng)用的一個(gè)更好的選擇。盡管它存在著缺點(diǎn)和實(shí)現(xiàn)挑戰(zhàn)。
總結(jié)
以上是生活随笔為你收集整理的c# 微服务学习_资深架构师学习笔记:什么是微服务?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php上传商品信息并显示,第37课 th
- 下一篇: 8255数码管显示0到9_汇编语言--键