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