「微服務架構是一種架構模式,它提倡將單一應用程式劃分成一組小的服務,服務之間相互協調、互相配合,為用戶提供最終價值。每個服務運行在其獨立的進程中,服務和服務之間採用輕量級的通信機制相互溝通(通常是基於HTTP的Restful API).每個服務都圍繞著具體的業務進行構建,並且能夠被獨立的部署到生產環境、類生產環境等。另外,應儘量避免統一的、集中的服務管理機制,對具體的一個服務而言,應根據業務上下文,選擇合適的語言、工具對其進行構」
單體應用 vs 微服務架構
優點
缺點
克裡斯·理查森(Chris Richardson)
世界著名的軟體大師,《POJOS in Action》等技術名著的作者,也是著名開源項目 Cloud Foundry 和 Eventuate 的創始人。他的研究領域包括微服務架構設計、分布式數據管理、事件驅動的應用架構 、領域驅動設計、持續交付、Spring 框架、Scala、NoSQL 資料庫等。
喻勇
在技術圈馳騁多年,曾擔任過微軟技術布道師,VMware Cloud Foundry 生態建設負責人,並有幸引領了國內容器技術的創業浪潮。目前定居加拿大,關注微服務架構、雲原生應用等領域。
本書的重點是架構和開發,適合負責開發和交付軟體的任何人閱讀。
側重於解釋微服務架構的設計模式和其他概念。無論讀者使用何種技術棧,我的目標都是讓你們可以輕鬆讀懂這本書。你只需要熟悉企業應用程式架構和設計的基礎知識即可。特別是,需要了解三層架構、Web應用程式設計、關係型資料庫、使用消息和基於REST的進程間通信,以及應用程式安全性的基礎知識等概念。本書的代碼示例使用Java 和Spring框架。為了充分利用它們,讀者應該對Spring框架有所了解。
第一、要記住微服務不是解決所有問題的萬能「銀彈」。
第二、編寫整潔的代碼和使用自動化測試至關重要,因為這是現代軟體開發的基礎。
第三、關注微服務的本質,即服務的分解和定義,而不是技術,如容器和其他工具。
第四、確保你的服務鬆耦合,並且可以獨立開發、測試和部署,不要搞成分布式單體(Distributed Monolith),那將會是巨大的災難。
第五、也是最重要的,不能只是在技術上採用微服務架構。擁抱DevOps的原則和實踐,在組織結構.上實現跨職能的自治團隊,這必不可少。還必須記住:實現微服務架構並不是你的目標。你的目標是加速大型複雜應用程式的開發。
1.1.1 FTGO應用程式的架構
FTGO應用程式是一個典型的分層模塊化企業級Java應用。圖1-1展示了它的架構。FTGO應用程式擁有一個六邊形的架構,我們會在第2章中詳細介紹這類架構風格。在這個六邊形中,應用程式的核心是業務邏輯組件。在業務邏輯外圍是各種用來實現用戶界面和與外部服務集成的適配器。
業務邏輯由包含了服務和領域對象的模塊組成,一些典型的模塊包括Order Management、Delivery Management、Billing和Payments。若干適配器用來完成與外部系統的對接工作,一些是入站(inbound)適配器,它通過調用業務邏輯來處理各類請求,包括REST API和Web用戶界面適配器。其他是出站(outbound)適配器,它使業務邏輯能夠訪問MySQL資料庫並調用Twilio和Stripe等雲服務。
儘管邏輯上FTGO是一個模塊化的架構,這個應用還是被整體打包成一個單一的WAR文件,部署運行在Tomcat之上。這是一個非常典型並且被廣泛應用的單體軟體架構風格:一個系統被作為單一的單元打包和部署。如果FTGO應用是採用GoLang語言編寫的,那它的交付形態就是一個單一的可執行文件;如果是用Ruby或者Node.js開發的,那它的交付形態就是一個目錄和它之下的子目錄中包含的各種原始碼。單體架構本身並不存在問題, FTGO開發人員在選擇單體架構時為他們的應用程式架構做出了一個很好的決定。
1.1.2 單體架構的好處:
在FTGO發展的早期,應用程式相對較小,單體架構具有以下好處。
但是,隨著時間的推移,開發、測試、部署和擴展都會變得更加困難。我們來看看為什麼。
1.1.3 什麼是單體地獄:
不幸的是,正如FTGO的開發人員已經意識到的,單體架構存在著巨大的局限性。類似FTGO這樣渴求成功的應用程式,往往都不斷地在單體架構的基礎之上擴展。每一次開發衝刺(Sprint),FTGO的開發團隊就會實現更多的功能,顯然這會導致代碼庫膨脹。而且,隨著公司的成功,研發團隊的規模不斷壯大。代碼庫規模變大的同時,團隊的管理成本也不斷提高。
如圖1-2所示,那個曾經小巧的、簡單的、由一個小團隊開發維護的FTGO應用程式,經過10年的成長,已經演變成一個由大團隊開發的巨無霸單體應用程式。同樣,小型開發團隊現在已成為多個所謂Scrum敏捷團隊,每個團隊都在特定的功能領域工作。作為架構擴展的結果,FTGO已經陷入了單體地獄。開發變得緩慢和痛苦。敏捷開發和部署已經不可能。我們來看看這是為什麼。
過度的複雜性會嚇退開發者
FTGO應用程式的首要問題是它的過度複雜性。這個系統本身過於龐大和複雜,以至於任何一個開發者都很難理解它的全部。因此,修復軟體中的問題和正確地實現新功能就變得困難且耗時。各種交付截止時間都可能被錯過。
更糟糕的是,這種極度的複雜性正在形成一個惡性循環:由於代碼庫太難於理解,因此開發人員在更改時更容易出錯,每一次更改都會讓代碼庫變得更複雜、更難懂。之前圖1-1所示的乾淨、模塊化架構並不能反映現實世界的真實情況。真實情況是FTGO應用正在一步一步地成為一個巨大的、令人費解的「髒泥球」。
瑪麗記得她曾經在某個技術會議上遇到一個極客,他開發了一個分析數以千計JAR文件和數百萬行代碼之間依賴關係的工具,那時候瑪麗覺得這個工具也許能幫助FTGO釐清頭緒。現在她並不這麼想。瑪麗認為更好的方法是遷移到更適合複雜應用程式的架構風格:微服務架構。
開發速度緩慢
因為要跟這些極度複雜的系統打交道,FTGO的開發人員發現他們日常的開發工作變慢了。這個巨大的項目把開發人員的IDE工具搞得很慢,構建一次FTGO應用需要很長時間,更要命的是,因為應用太大,每啟動一次都需要很長的時間。因此,從編輯到構建、運行再到測試這個周期花費的時間越來越長,這嚴重地影響了團隊的工作效率。
從代碼提交到實際部署的周期很長,而且容易出問題
另一個困擾FTGO應用團隊的問題是:把程序更改部署到生產環境的時間變得更長,整個流程幾乎令人抓狂。目前團隊每月對生產環境進行一次更新部署,通常都是在周五或者周六的晚上。瑪麗總是讀到一些關於SaaS應用持續部署的「黑科技」:每天都可以在業務時間對應用進行多次修改並快速完成部署。顯然,對於像Amazon.com這樣的公司,2011年就已經能夠做到每11.6秒完成一次變更到生產環境的部署。一個月完成幾次更新,對FTGO開發人員來說簡直就是神話。實現持續部署更是遙不可及的夢想。
FTGO的敏捷實踐是不完整的。工程團隊被分成各個小隊(squad),以兩周為一個衝刺周期。不幸的是,從代碼完成到運行在生產環境是一個漫長且費力的過程。一個問題是,眾多開發人員都向同一個代碼庫提交代碼更改,這常常使得這個代碼庫的構建結果處於無法交付的狀態。當FTGO嘗試採用功能分支來解決這個問題時,帶來的是漫長且痛苦的合併過程。緊接著,一旦團隊完成一個衝刺任務,隨後迎接他們的將是一個漫長的測試和代碼穩定周期。
把更改推向生產環境的另一個挑戰是運行測試需要很長時間。因為代碼庫如此複雜,以至於一個更改可能引起的影響是未知的,為了避免牽一髮而動全身的後果,即使是一個微小的更改,開發人員也必須在持續集成伺服器上運行所有的測試套件。系統的某些部分甚至還需要手工測試。如果測試失敗,診斷和修復也需要更多的時間。因此,完成這樣的測試往往需要數天甚至更長時間。
難以擴展
FTGO團隊在對應用進行橫向擴展時也遇到了挑戰。因為在有些情況下,應用的不同模塊對資源的需求是相互衝突的。例如,餐館數據保存在一個大型的內存資料庫中,理想情況下運行這個應用的伺服器應該有較大容量的內存。另外,圖片處理模塊又需要比較快的CPU來完成圖形運算,這需要應用部署在具有多個高性能CPU的伺服器之上。因為這些模塊都是在一個應用程式內,因此FTGO在選用伺服器時必須滿足所有模塊的需要。
交付可靠的單體應用是一項挑戰
FTGO應用的另一個問題是缺乏可靠性,這個問題導致了頻繁的系統故障和宕機。系統不可靠的一個原因是應用程式體積龐大而無法進行全面和徹底的測試。缺乏可靠的測試意味著代碼中的錯誤會進入生產環境。更糟糕的是,該應用程式缺乏故障隔離,因為所有模塊都在同一個進程中運行。每隔一段時間,在一個模塊中的代碼錯誤,例如內存洩漏,將會導致應用程式的所有實例都崩潰。 FTGO開發人員不喜歡在半夜因為生產環境的故障而被叫醒。業務人員也對由此造成的收入損失和喪失客戶信任而頭疼不已。
需要長期依賴某個可能已經過時的技術棧
FTGO所經歷的單體地獄的最終表現,也體現在團隊必須長期使用一套相同的技術棧方面。單體架構使得採用新的框架和程式語言變得極其困難。在單體應用上採用新技術或者嘗試新技術都是極其昂貴和高風險的,因為這個應用必須被徹底重寫。結果就是,開發者被困在了他們一開始選擇的這個技術之內。有時候這也就意味著,團隊必須維護一個正在被廢棄或過時的技術所開發的應用程式。
Spring框架本身保持著持續的演進和更新,同時維持著向後的兼容性。所以理論上來說FTGO可以隨著升級。不幸的是,FTGO的應用程式使用了與Spring新版本不兼容的框架,開發團隊也擠不出時間來更新這些舊框架。久而久之,這個應用的絕大部分都被捲入了這個已經過時的框架。更不幸的是,FTGO的開發人員一直想嘗試類似GoLang和Node.js這樣的非JVM類程式語言,然而在單體架構之下,這是做不到的。
1.2 為什麼本書與你有關:
如果你正在翻看這本書,那麼你很可能是軟體開發人員、架構師、CTO或工程研發的副總裁。你負責的應用程式已超出其單體架構所能夠支撐的範圍,就像FTGO的瑪麗一樣,你正在努力應對軟體交付,並想知道如何逃避單體地獄。或許你擔心你的組織正在走向單體地獄之路,你想知道如何在為時已晚之前改變方向。如果你需要讓手中的軟體項目避免陷入單體地獄,那麼這本書就是為你所寫。
本書花了很多時間來解釋微服務架構的概念。無論你現在使用何種技術棧,我的目標都是讓你可以輕鬆地讀懂這本書。你所需要的只是熟悉企業應用程式架構設計的基礎知識。特別是,你需要了解以下內容:
本書中的代碼示例是使用Java和Spring框架編寫的。這意味著為了充分利用這些示例,你還需要熟悉Spring框架。
1.3 你會在本書中學到什麼:
讀完這本書後,你會理解和掌握如下知識:
你也會掌握如下技術:
1.4 拯救之道:微服務架構
瑪麗意識到,FTGO應用程式必須遷移為微服務架構。
有趣的是,軟體架構其實對功能性需求影響並不大。事實上,在任何架構甚至是一團糟的架構之上,你都可以實現一組用例(應用的功能性需求)。因此,即使是成功的應用程式(例如FTGO),其內部架構也往往是一個大泥球。
架構的重要性在於它影響了應用的非功能性需求,也稱為質量屬性或者其他的能力(-ilities)。隨著FTGO應用的增長,各種質量屬性和問題都浮出水面,最顯著的就是影響軟體交付速度的可維護性、可擴展性和可測試性。
一方面,訓練有素的團隊可以減緩項目陷入單體地獄的速度。團隊成員可以努力維護他們的模塊化應用。他們也可以編寫全面的自動化測試。但是另一方面,他們無法避免大型團隊在單體應用程式上協同工作的問題,也不能解決日益過時的技術棧問題。團隊所能做的就是延緩項目陷入單體地獄的速度,但這是不可避免的。為了逃避單體地獄,他們必須遷移到新架構:微服務架構。
今天,針對大型複雜應用的開發,越來越多的共識趨向於考慮使用微服務架構。但微服務到底是什麼?不幸的是,微服務這個叫法本身暗示和強調了尺寸。針對微服務架構有多種定義。有些僅僅是在字面意義上做了定義:服務應該是微小的不超過100行代碼,等等。另外有些定義要求服務的開發周期必須被限制在兩周之內。曾在Netflix工作的著名架構師Adrian Cockcroft把微服務架構定義為面向服務的架構,它們由鬆耦合和具有邊界上下文的元素組成。這個定義不錯,但仍舊有些複雜難懂。我們來嘗試一個更好的定義。
由於字數原因接下來把目錄截取給大家觀看,需要完整PDF版的朋友轉發+關注後私信「微服務」免費獲取;
第1章 逃離單體地獄
第2章 服務的拆分策略
第3章 微服務架構中的進程間通信
第4章 使用Saga管理事務
第5章 微服務架構中的業務邏輯設計
第6章 使用事件溯源開發業務邏輯
第7章 在微服務架構中實現查詢
第8章 外部API模式
第9章 微服務架構中的測試策略(上)
第10章 微服務架構中的測試策略(下)
第11章 開發面向生產環境的微服務應用
第12章 部署微服務應用
第13章 微服務架構的重構策略
設計模式類的書籍大多非常抽象,但是這本書竟然能把微服務構建和實施過程中的的細節(或坑點)講的如此清楚,真的很難得。國內這兩年也出過不少微服務的書,但大多是講「術」而不是「道」,而我認為,對於微服務方案來講,「術」是最容易搞定的,比如你來個SpringCloud全家桶,「術」的問題就基本解決,更何況,SpringCloud/SpringBoot本身非常容易上手使用,讓大家有一種我學會它就會做微服務一樣的錯覺,有時候這種錯覺真的會害死人,大家不妨看看身邊有多少工程是為了微服務而微服務...而這本書,以「道」為主,清晰講解實施微服務的過程中,我們需要關注哪些問題,解決方案有哪些,然後輔以「術」,讓人讀起來非常爽。另外,這本書不太適合初級工程師,比較適合有一定工程實踐經驗的中高級工程師或架構師們看看!
這份PDF領取方式也簡單,作為電子版全網首發,需要領取的朋友麻煩幫忙轉發轉發這篇文章+關注小編,然後私信小編【微服務】三個字。