NGINX微服務(一):微服務簡介

Nginx 軟件 圖像處理 Tomcat ITPie ITPie 2017-08-29

鏈接:https://github.com/oopsguy/microservices-from-design-to-deployment-chinese

譯者:Oopsguy

目前微服務受到很多關注:文章、博客、社交媒體上的討論和會議演講。他們正在迅速走向加德納技術成熟度曲線(Gartner Hype cycle)的高峰。與此同時,也有持懷疑態度的軟件社區人員認為微服務沒什麼新鮮可言。反對者聲稱它的思想只是面向服務架構(SOA)的重塑。然而,無論是炒作還是懷疑,不可否認微服務架構模式具有非常明顯的優勢——特別是在實施敏捷開發和複雜的企業應用交付方面。

本章節是七章之中介紹關於的設計、構建和部署微服務方面的內容。您將瞭解微服務的由來和與傳統單體應用模式的比較。這本電子書描述了許多關於微服務架構方面的內容。無論是對您的項目的意義,或者是如何去應用它,您都將瞭解到微服務架構模式的優點和缺點。

我們先來看看為什麼要考慮使用微服務。

1.1、構建單體應用

我們想一下,您開始製作一個新的打車應用,打算與 Uber 和 Hailo 競爭。經過初步交流與需求收集,您將手動或者使用類似 Rails、Spring Boot、Play或者Maven等平臺來生成一個新項目。

這個新應用是一個模塊化的六邊形架構,如圖 1-1 所示:

NGINX微服務(一):微服務簡介

應用程序的核心是由模塊實現的業務邏輯,它定義了服務、領域對象和事件。圍繞核心的是與外部世界接口對接的適配器。適配器示例包括了數據庫訪問組件、生產和消費消息的消息組件和 web 組件,它們暴露了 API 或者實現了一個 UI。

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

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

1.2、走向單體地獄

不幸的是,這種簡單的方法有很大的侷限性。成功的應用有一個趨勢,隨著時間推移而變得越來越臃腫。在每個衝刺時期,您的開發團隊實現了更多的用戶需求,這意味著添加了許多行代碼。幾年之後,您的小而簡單的應用將會逐漸成長為龐然大物似的單體。為了給出一個極端的示例,我最近和一位開發者做了交談,他正在編寫一個工具用於從他們的數百萬行代碼(lines of code,LOC)應用中分析數千個 JAR 之間的依賴。我相信這是大量開發者在多年齊心協力下創造了這樣的野獸。

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

應用程序的規模也將減緩發展。應用程序越大,啟動的時間越長。我調查過開發者們的單體應用的大小和性能,一些報告的啟動時間為 12 分鐘。我也聽說過應用程序啟動需要 40 分鐘以上的怪事。如果開發人員經常要重啟應用服務器,那麼很大一部分時間都是在等待中度過,他們的生產力將受到限制。

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

當不同模塊存在資源需求衝突時,單體應用也可能難以擴展。例如,一個模塊可能會執行 CPU 密集型圖像處理邏輯,理想情況下是部署在 Amazon EC2 Compute Optimized 實例中。另一個模塊可能是內存數據庫,最適合 EC2 Memory-optimized 實例。然而,因為這些模塊被部署在一起,您必須在硬件選擇上做出妥協。

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

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

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

那麼您能做些什麼呢?

1.3、微服務-解決複雜問題

許多組織,如 Amazon、eBay 和 Netflix,已經採用現在所謂的微服務架構模式解決了這個問題,而不是構建一個臃腫的單體應用。它的思路是將您的應用程序分解成一套較小的互連服務。

一個服務通常實現了一組不同的特性或者功能,例如訂單管理、客戶管理等。每一個微服務都是一個迷你應用,它自己的六邊形架構包括業務邏輯以及多個適配器。

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

例如,前面描述的系統可能分解成如圖 1-2 所示:

NGINX微服務(一):微服務簡介

應用程序的每個功能區域現在都由自己的微服務實現。此外,Web 應用程序被分為一組更簡單的 Web 應用程序。例如,以我們的出粗車為例,一個專門是乘客的,一個專門是司機的。這使得它更容易地為特定的用戶、司機、設備或者專門的用例部署不同的場景。每個後端服務暴露一個 REST API,大部分的服務消費由其他服務提供的 API。例如,司機管理使用了通知服務器來告知一個可用司機關於一個潛在路程。UI 服務調用了其他服務來渲染頁面。服務也可以使用異步、基於消息的通信。本電子書後面將會詳細介紹服務間的通信。

一些 REST API 也暴露給移動端應用供司機和乘客使用。然而,應用不能直接訪問後端服務。相反,他們之間的通信是由一個稱為 API 網關(API Cateway)的中介負責。API 網關負責負載均衡、緩存、訪問控制、API計量和監控,可以通過使用 NGINX 來實現。第 2 章詳細討論 API 網關。

NGINX微服務(一):微服務簡介

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

應用程序通常將這三種類型的座標方式一起使用。Y 軸座標將應用分解成微服務,如圖 1-2 所示。

在運行時,X 座標軸上運行著服務的多個實例,每一個服務配合負載均衡器以滿足吞吐量和可用性。某些應用程序也有可能使用 Z 座標軸來進行分區服務。圖 1-4 展示瞭如何用 Docker 將旅途管理(Trip Management)服務部署到 Amazon EC2 上運行。

NGINX微服務(一):微服務簡介

在運行時,旅途管理服務由多個服務實例組成,每個服務實例是一個 Docker 容器。為了實現高可用,容器是在多個雲虛擬機上運行的。服務實例的前方是一個如 NGINX 的負載均衡器,用於跨實例分發請求。負載均衡器也可以處理其他問題,如緩存、訪問控制、API 度量和監控。

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

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

NGINX微服務(一):微服務簡介

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

1.4、微服務的優點

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

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

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

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

1.5、微服務的缺點

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

微服務另一個主要的缺點是由於微服務是一個分佈式系統而變得複雜。開發者需要選擇和實現基於消息或者 RPC 的進程間通信機制。此外,由於目標請求可能很慢或者不可用,他們還必須編寫代碼來處理部分故障。雖然這些都不是很複雜高深的事,但模塊間通過語言級方法/過程調用相互調用,這比單體應用要複雜得多。

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

測試微服務應用程序也很複雜。例如,使用現代的框架如 Sprig 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 等容器技術相結合。在本書最後我們將看到基於軟件的應用交付方式如 NGINX 是如何在微服務級別處理緩存、訪問控制、API 計量和監控,可以幫助解決這個問題。

1.6、總結

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

在後面的章節中,我將介紹微服務架構的方方面面並探討諸如服務發現、服務部署方案以及將單體應用重構為服務的策略。

微服務實戰:NGINX Plus 作為反向代理服務器

By Floyd Smith

10000 個網站中有超過 50% 使用 NGINX,這主要是因為它具有作為反向代理服務器的能力。您可以 NGINX 放在當前應用程序前面甚至是數據庫服務器以獲取各種功能 —— 更高的性能、更高的安全性、可擴展性、靈活性等。你現有的應用程序只需要配置代碼和作出很少或無需改變。對於存在性能壓力的站點,或者預計未來存在高負荷,效果看起來似乎沒那麼神奇。

那麼這與微服務有什麼關係呢?實現一個反向代理服務器,並使用 NGINX 的其他功能來為您提供架構靈活性。反向代理服務器、靜態和應用文件緩存、SSL/TLS 和 HTTP/2 都會從您的應用程序剔除。讓應用程序只做它該做的事,NGINX 還可作為負載均衡器,微服務實施過程中的一個關鍵角色。先進的 NGINX Plus 的功能包含了複雜的負載均衡算法、多種方式的會話持久和管理監控,這些對微服務尤其有用(NGINX 最近還增加了使用 DNS SRV 記錄的服務發現支持,這是一個頂尖的功能)。而且,如本章所述,NGINX 可以自動化部署微服務。

此外,NGINX 還提供了必要的功能來支撐 NGINX 微服務參考架構中的三大模型。代理模型使用 NGINX 作為 API 網關;網格路由模型使用了一個額外的 NGINX 作為進程間通信中樞;Fabric 模型中每個微服務使用一個 NGINX 來控制 HTTP 流量,在微服務之間實現 SSL/TLS,這非常具有突破性。

相關推薦

推薦中...