作者:成富单旁,資深架構(gòu)師沪羔,擁有多年一線開發(fā)經(jīng)驗(yàn),曾就職于IBM象浑,后移居海外創(chuàng)業(yè)蔫饰,現(xiàn)任公司首席軟件工程師琅豆,負(fù)責(zé)基于微服務(wù)架構(gòu)的云原生產(chǎn)品研發(fā)。資深技術(shù)作家篓吁,著有多部中英文技術(shù)書籍:《深入理解 Java7 》《Exploring Java9》等趋距。
*本文經(jīng)作者授權(quán)整理發(fā)布,內(nèi)容選自《云原生微服務(wù)架構(gòu)實(shí)戰(zhàn)精講》
這兩年越除,微服務(wù)作為一種架構(gòu)方式节腐,已經(jīng)從論壇熱詞走向了真正的技術(shù)熱點(diǎn),?諸多大廠(比如?Amazon摘盆、Netflix翼雀、螞蟻金服、網(wǎng)易云音樂等)已經(jīng)遷移并采用了微服務(wù)架構(gòu)孩擂。市面上微服務(wù)的圖書狼渊、教程也層出不窮,為什么互聯(lián)網(wǎng)行業(yè)如此擁抱微服務(wù)类垦?了解一下行業(yè)發(fā)展問題和微服務(wù)架構(gòu)的優(yōu)勢(shì)狈邑,也就不難理解了。
目前蚤认,我們開發(fā)的大部分應(yīng)用都是單體應(yīng)用米苹。當(dāng)單體應(yīng)用的復(fù)雜度增加時(shí),會(huì)出現(xiàn)一系列的問題砰琢。
單體應(yīng)用的問題:
第 1 個(gè)問題是單體應(yīng)用過于復(fù)雜蘸嘶,超出了單個(gè)開發(fā)人員的理解能力。雖然可以通過組件化把單體應(yīng)用劃分成多個(gè)單元陪汽,降低每個(gè)單元的復(fù)雜度训唱,但在實(shí)際開發(fā)中,組件化的效果并不是很好挚冤。一方面是因?yàn)楣泊a的存在况增,這些共享的代碼由于被多個(gè)組件使用,難以高效更新训挡;另一方面由于文檔缺失和開發(fā)過程中的各種不規(guī)范行為澳骤,造成組件之間的接口不清晰。在 Java 代碼中舍哄,我們可以很容易地調(diào)用其他組件中的接口和類的方法宴凉,從而在不同組件之間有意或無意的引入依賴。所產(chǎn)生的結(jié)果就是單體應(yīng)用中不同組件之間的依賴關(guān)系非常復(fù)雜表悬。
第 2 個(gè)問題是緩慢的開發(fā)速度弥锄。當(dāng)應(yīng)用變得復(fù)雜時(shí),開發(fā)人員則需要花費(fèi)更多的時(shí)間來理解所做的改動(dòng)對(duì)已有代碼的潛在影響。經(jīng)常遇到的情況有籽暇,一個(gè)看似很小的改動(dòng)温治,會(huì)對(duì)應(yīng)用造成很大的影響。當(dāng)這樣的情況出現(xiàn)多次之后戒悠,開發(fā)人員由于怕承擔(dān)責(zé)任熬荆,變得不情愿改進(jìn)代碼的質(zhì)量,同時(shí)绸狐,在本地開發(fā)環(huán)境上進(jìn)行開發(fā)和調(diào)試變得更加耗時(shí)卤恳。在 IDE 中修改代碼之后,編譯和重啟應(yīng)用的時(shí)間過長(zhǎng)寒矿,本地單元測(cè)試也需要更長(zhǎng)的時(shí)間來運(yùn)行突琳。所產(chǎn)生的結(jié)果就是開發(fā)人員的寶貴時(shí)間耗費(fèi)在無意義的等待上。
第 3 個(gè)問題是應(yīng)用的擴(kuò)展變得很困難符相。當(dāng)應(yīng)用的處理能力不能滿足業(yè)務(wù)需求時(shí)拆融,需要進(jìn)行擴(kuò)展,擴(kuò)展分為垂直擴(kuò)展和水平擴(kuò)展兩種啊终。垂直擴(kuò)展的做法是增加單個(gè)應(yīng)用實(shí)例所能使用的資源镜豹,這導(dǎo)致的問題是不同組件對(duì)資源需求的沖突,有些組件對(duì)內(nèi)存的消耗較大蓝牲,而另外一些組件對(duì) CPU 的要求高趟脂,當(dāng)無法同時(shí)滿足兩者時(shí),則需要作出取舍搞旭。水平擴(kuò)展的做法是增加應(yīng)用的實(shí)例數(shù)量散怖,水平擴(kuò)展只能以應(yīng)用為單位來進(jìn)行,如前面的圖片所示肄渗,應(yīng)用中不同組件的負(fù)載程度是不同的,以電子商務(wù)應(yīng)用為例咬最,商品展示和訂單處理相關(guān)組件的負(fù)載要大于客戶服務(wù)相關(guān)的組件翎嫡,以應(yīng)用為單元的擴(kuò)展方式無法有效的分配資源。
第 4 個(gè)問題是新版本更新上線的速度變慢永乌。現(xiàn)在的應(yīng)用都要求能夠及時(shí)響應(yīng)用戶的需求惑申,以最快的速度添加新功能和修復(fù)問題,這意味著一天可能要進(jìn)行很多次的產(chǎn)品更新翅雏。單體應(yīng)用由于復(fù)雜度高圈驼,每一次代碼提交之后的持續(xù)集成所花費(fèi)的時(shí)間過長(zhǎng)。由于需要運(yùn)行全部的測(cè)試用例望几,限制了更新的頻率绩脆。
第 5 個(gè)問題是整個(gè)應(yīng)用的穩(wěn)定性變差。由于整個(gè)應(yīng)用只有一個(gè)進(jìn)程,組件之間缺少必要的隔離性靴迫,任何一個(gè)組件中出現(xiàn)的問題惕味,比如內(nèi)存泄漏,都會(huì)導(dǎo)致整個(gè)應(yīng)用的崩潰玉锌。當(dāng)某個(gè)組件占用大量的 CPU 和內(nèi)存資源時(shí)名挥,會(huì)導(dǎo)致其他組件由于資源不足而無法正常工作。
第 6 個(gè)問題是技術(shù)棧的選型和更新變得困難主守。單體應(yīng)用通常只使用單一的技術(shù)棧禀倔,包括編程語言、所用框架参淫、第三方庫救湖,以及數(shù)據(jù)庫和消息中間件等,這就要求所有的開發(fā)人員都掌握相同的技術(shù)棧黄刚,事實(shí)上捎谨,不同組件由于需求的不同,有它最適合的技術(shù)棧憔维。強(qiáng)制使用單一技術(shù)棧涛救,無疑會(huì)對(duì)開發(fā)效率產(chǎn)生影響,一旦技術(shù)棧選型確定之后业扒,要對(duì)它進(jìn)行更新是一件非常困難的事情检吆,整個(gè)應(yīng)用都可能受到影響。所產(chǎn)生的效果就是應(yīng)用的技術(shù)棧不斷的老化程储,帶來更多的問題蹭沛,形成惡性循環(huán)。
如果你的單體應(yīng)用遇到了上述問題章鲤,則說明該應(yīng)用的架構(gòu)到了需要調(diào)整的時(shí)候摊灭,微服務(wù)架構(gòu)則是針對(duì)以上問題的解決方案。下面我們來看一下微服務(wù)架構(gòu)到底是什么败徊?
微服務(wù)架構(gòu)的核心思想是把應(yīng)用按照功能劃分成多個(gè)獨(dú)立的服務(wù)帚呼,每個(gè)服務(wù)都是獨(dú)立運(yùn)行的應(yīng)用。
如下圖所示皱蹦,外部的邊框是應(yīng)用的邊界煤杀,不同的形狀表示不同的單元。圖中左側(cè)表示的是單體應(yīng)用沪哺,所有單元在同一個(gè)應(yīng)用的邊界內(nèi)沈自。在進(jìn)行擴(kuò)展時(shí),單體應(yīng)用只能整體擴(kuò)展辜妓;右側(cè)表示的是微服務(wù)架構(gòu)的應(yīng)用枯途,每個(gè)單元在自己的應(yīng)用邊界內(nèi)忌怎。在進(jìn)行擴(kuò)展時(shí),微服務(wù)架構(gòu)的應(yīng)用以服務(wù)為單位進(jìn)行擴(kuò)展柔袁。不同服務(wù)在運(yùn)行時(shí)的實(shí)例數(shù)量可以根據(jù)負(fù)載動(dòng)態(tài)進(jìn)行調(diào)整呆躲。
微服務(wù)架構(gòu)的特征:
1.微服務(wù)架構(gòu)使用服務(wù)作為組件化的單元。組件化是軟件開發(fā)中的基本實(shí)踐捶索,在 Java 應(yīng)用開發(fā)中插掂,組件通常以 JAR 文件的形式出現(xiàn),Maven 倉庫中包含了海量的第三方庫可供使用腥例,Java 開發(fā)人員都熟悉這種使用組件的方式辅甥。在微服務(wù)架構(gòu)中,組件的單元變成了服務(wù)燎竖,服務(wù)運(yùn)行在獨(dú)立的進(jìn)程中璃弄,不能通過直接的方法調(diào)用來訪問,而需要使用類似 HTTP 這樣的進(jìn)程間通信方式构回,每個(gè)服務(wù)可以獨(dú)立部署夏块,使用 API 規(guī)范來描述其公開接口。一個(gè)微服務(wù)只能通過 API 訪問另外的微服務(wù)纤掸,并不能訪問內(nèi)部的實(shí)現(xiàn)代碼脐供。
如下圖所示,不同服務(wù)之間存在調(diào)用關(guān)系借跪,調(diào)用的方式可以是 REST 或 gRPC政己。
2.微服務(wù)架構(gòu)的開發(fā)團(tuán)隊(duì)圍繞業(yè)務(wù)能力來組織。單體應(yīng)用的開發(fā)團(tuán)隊(duì)通常按照技能來劃分掏愁,一個(gè)典型的 3 層應(yīng)用開發(fā)團(tuán)隊(duì)可能分成前端開發(fā)歇由、后端開發(fā)和數(shù)據(jù)庫管理等小組。微服務(wù)架構(gòu)的開發(fā)團(tuán)隊(duì)以服務(wù)為單元來組織果港,每個(gè)服務(wù)與特定的業(yè)務(wù)需求相對(duì)應(yīng)沦泌。服務(wù)的開發(fā)團(tuán)隊(duì)規(guī)模較小,包含開發(fā)辛掠、測(cè)試和 DevOps 相關(guān)的全部人員赦肃,負(fù)責(zé)該微服務(wù)的團(tuán)隊(duì)對(duì)該微服務(wù)的實(shí)現(xiàn)可以全權(quán)負(fù)責(zé)。較小的開發(fā)團(tuán)隊(duì)意味著更少的溝通成本和更高的開發(fā)效率公浪。
3.微服務(wù)架構(gòu)使用去中心化的管理模式。單體應(yīng)用的開發(fā)團(tuán)隊(duì)通常會(huì)對(duì)使用的技術(shù)棧做出限制船侧,要求整個(gè)團(tuán)隊(duì)使用統(tǒng)一的技術(shù)棧欠气。這種方式的弊端在于,沒有一種技術(shù)棧適用于解決所有的問題镜撩。微服務(wù)架構(gòu)中的服務(wù)都可以獨(dú)立部署预柒,這就意味著每個(gè)服務(wù)在實(shí)現(xiàn)時(shí)可以選擇最適合的技術(shù)棧队塘,只需要滿足服務(wù)的 API 契約即可。每個(gè)團(tuán)隊(duì)自主管理所負(fù)責(zé)的服務(wù)宜鸯,不但負(fù)責(zé)構(gòu)建憔古,還同樣負(fù)責(zé)運(yùn)行和維護(hù),這在無形中提高了團(tuán)隊(duì)的主觀能動(dòng)性淋袖,同時(shí)降低了管理的開銷鸿市。
如下圖所示,每個(gè)微服務(wù)都有對(duì)應(yīng)的團(tuán)隊(duì)即碗,而每個(gè)團(tuán)隊(duì)中都有各種角色的人員焰情。
4.微服務(wù)架構(gòu)使用去中心的數(shù)據(jù)存儲(chǔ)。單體應(yīng)用通常使用單一數(shù)據(jù)庫來存儲(chǔ)數(shù)據(jù)剥懒,微服務(wù)架構(gòu)中的服務(wù)通常有自己專有的數(shù)據(jù)存儲(chǔ)内舟,如下圖所示。這些存儲(chǔ)方式的實(shí)現(xiàn)可能各不相同初橘,只包含服務(wù)所需的數(shù)據(jù)验游。
5.微服務(wù)架構(gòu)強(qiáng)調(diào)基礎(chǔ)設(shè)施的自動(dòng)化。持續(xù)集成和持續(xù)部署都是通用的實(shí)踐保檐,單體應(yīng)用由于只有一個(gè)部署單元耕蝉,對(duì)自動(dòng)化的要求并不高。微服務(wù)架構(gòu)中的服務(wù)可以獨(dú)立部署展东,但當(dāng)服務(wù)的數(shù)量較多時(shí)赔硫,必須通過自動(dòng)化的流程來完成。
微服務(wù)架構(gòu)的實(shí)現(xiàn):
微服務(wù)架構(gòu)所涵蓋的內(nèi)容非常廣泛盐肃,對(duì)不同角色的人員爪膊,其意義并不相同:
從架構(gòu)的角度來說,它是由多個(gè)獨(dú)立服務(wù)組成的分布式系統(tǒng)砸王;
從人員管理的角度來說推盛,它要求員工組成小而完備的自主團(tuán)隊(duì);
從項(xiàng)目管理的角度來說谦铃,它推薦使用敏捷軟件開發(fā)流程耘成,如 Scrum 或 Kanban;
從開發(fā)的角度來說驹闰,每個(gè)服務(wù)有獨(dú)立的業(yè)務(wù)邏輯實(shí)現(xiàn)和數(shù)據(jù)存儲(chǔ)瘪菌,使用開放 API 作為邊界;
從測(cè)試的角度來說嘹朗,需要對(duì)服務(wù)的 API 契約進(jìn)行測(cè)試师妙;
從運(yùn)維的角度來說,持續(xù)集成和持續(xù)部署對(duì)微服務(wù)架構(gòu)的成功至關(guān)重要屹培。
微服務(wù)架構(gòu)的實(shí)踐是一項(xiàng)系統(tǒng)化的工程默穴,需要很多人的協(xié)同合作怔檩。作為開發(fā)人員,我們更多關(guān)注的是如何完成服務(wù)的實(shí)現(xiàn)蓄诽,但除了每個(gè)服務(wù)本身的實(shí)現(xiàn)之外薛训,還包括與其他服務(wù)的協(xié)作。
從實(shí)現(xiàn)的角度來說仑氛,我們需要考慮表中的這些因素乙埃。
表中列出的關(guān)于服務(wù)實(shí)現(xiàn)的相關(guān)內(nèi)容,在大部分微服務(wù)架構(gòu)的應(yīng)用中都會(huì)出現(xiàn)调衰。但在實(shí)際的項(xiàng)目開發(fā)中膊爪,你并不會(huì)從零開始實(shí)現(xiàn)所有相關(guān)的內(nèi)容,而是使用已有的平臺(tái)嚎莉、框架和技術(shù)米酬,流行的技術(shù)選擇包括 Netflix OSS 棧、Spring Cloud 和 Kubernetes 等趋箩。
Netflix 是微服務(wù)架構(gòu)實(shí)踐中的引領(lǐng)者赃额,不僅在生產(chǎn)系統(tǒng)中成功應(yīng)用了微服務(wù)架構(gòu),還把相關(guān)的庫和工具以開放源代碼的形式共享出來叫确,形成了 Netflix OSS 棧跳芳。
Spring Cloud?是由多個(gè)開源項(xiàng)目組成的開發(fā)套件,用來實(shí)現(xiàn)分布式系統(tǒng)中的常見模式竹勉,如配置管理飞盆、服務(wù)發(fā)現(xiàn)和斷路器等,可以用來實(shí)現(xiàn)微服務(wù)架構(gòu)的應(yīng)用次乓。它的優(yōu)勢(shì)在于提供了一個(gè)抽象框架吓歇,可以避免供應(yīng)商鎖定的問題,對(duì)于同一個(gè)模式票腰,它可以切換底層的實(shí)現(xiàn)方式城看。Spring Cloud 本身是基于 Spring 框架的,對(duì)于一直工作在 Spring 框架上的團(tuán)隊(duì)來說杏慰,Spring Cloud 是一個(gè)不錯(cuò)的選擇测柠。
Kubernetes?是管理容器化工作負(fù)載和服務(wù)的平臺(tái),同時(shí)也是容器編排平臺(tái)缘滥,微服務(wù)及其依賴的其他服務(wù)通常以容器的形式運(yùn)行轰胁。Kubernetes 對(duì)表中的很多需求都提供了原生的解決方案,對(duì)于另外的一些需求則有開源實(shí)現(xiàn)朝扼,是運(yùn)行微服務(wù)架構(gòu)應(yīng)用的良好平臺(tái)软吐。
微服務(wù)架構(gòu)所包含的內(nèi)容非常多,在本文中吟税,我著重介紹了微服務(wù)架構(gòu)的基本概念凹耙,從單體應(yīng)用的問題來闡述引入微服務(wù)架構(gòu)的必要性,以及微服務(wù)架構(gòu)的應(yīng)用具備的特征肠仪。
在微服務(wù)的實(shí)現(xiàn)上肖抱,還有許多具體的問題,比如如何拆分服務(wù)异旧,服務(wù)之間如何協(xié)作意述,這些內(nèi)容,都會(huì)在我的專欄《云原生微服務(wù)架構(gòu)實(shí)戰(zhàn)精講》中做具體的闡述吮蛹。
感興趣的話荤崇,你可以點(diǎn)擊查看我的專欄簡(jiǎn)介,本章節(jié)內(nèi)容也會(huì)有更詳細(xì)的補(bǔ)充潮针,比如微服務(wù)架構(gòu)存在哪些問題术荤,下一講我將詳述“什么是 Docker 與容器化技術(shù)”,歡迎你來收聽每篷。