|
論如何正確實(shí)施微服務(wù)架構(gòu)的10個(gè)技巧? 作者 | Md Kamaruzzaman 譯者 | 蘇本如,責(zé)編 | Elle 出品 | CSDN(ID:CSDNnews) 以下為譯文: 微服務(wù)架構(gòu)到底是什么呢?以下是我給出的定義: 微服務(wù)架構(gòu)是將軟件系統(tǒng)分解為自主模塊,自主模塊可以獨(dú)立部署,通過(guò)輕量級(jí)的、與語(yǔ)言無(wú)關(guān)的方式進(jìn)行通信,共同實(shí)現(xiàn)業(yè)務(wù)目標(biāo)。 軟件系統(tǒng)通常非常復(fù)雜。由于人腦只能處理一定程度的復(fù)雜性,因此大型軟件系統(tǒng)的高復(fù)雜性會(huì)帶來(lái)很多問(wèn)題。一個(gè)大型的、復(fù)雜的軟件系統(tǒng)通常很難開(kāi)發(fā)、增強(qiáng)、維護(hù)、難以實(shí)現(xiàn)現(xiàn)代化和規(guī)?;?。許多年來(lái),人們作了很多嘗試,以解決軟件系統(tǒng)的復(fù)雜性難題。 20世紀(jì)70年代,David Parnas和Edsger W. Dijkstra引入了模塊化軟件開(kāi)發(fā),來(lái)解決這一復(fù)雜性問(wèn)題。20世紀(jì)90年代,為了解決業(yè)務(wù)應(yīng)用的復(fù)雜性,引入了分層軟件架構(gòu)。 到了21世紀(jì)初,面向服務(wù)的體系結(jié)構(gòu)(Service-Oriented Architecture,SOA)成為開(kāi)發(fā)復(fù)雜業(yè)務(wù)應(yīng)用程序的主流。而微服務(wù)架構(gòu)則是處理現(xiàn)代軟件應(yīng)用復(fù)雜性的最新方法。那么可能有人會(huì)問(wèn):為什么我們突然需要一種新的軟件開(kāi)發(fā)方法呢? 簡(jiǎn)單來(lái)說(shuō),這是因?yàn)樵谶^(guò)去的十年里,軟件開(kāi)發(fā)所處的生態(tài)系統(tǒng)發(fā)生了巨大的變化?,F(xiàn)在,軟件通常是使用敏捷方法開(kāi)發(fā),使用CI/CD方法部署在容器 云(Container Cloud)上,數(shù)據(jù)保存在NoSQL數(shù)據(jù)庫(kù)上,最后呈現(xiàn)在現(xiàn)代瀏覽器或智能手機(jī)上,并且這些機(jī)器通過(guò)高速網(wǎng)絡(luò)連接在一起。 基于這些因素,微服務(wù)架構(gòu)于2012年應(yīng)運(yùn)而生。 微服務(wù)vs.單一體系架構(gòu) 對(duì)于微服務(wù)架構(gòu)與單一體系架構(gòu),兩類人的觀點(diǎn)截然相反。一類人認(rèn)為,微服務(wù)架構(gòu)是一種盲目模仿(Cargo-Cult)、或者趨勢(shì)驅(qū)動(dòng)(Hype Driven)式的開(kāi)發(fā)方式,對(duì)于技術(shù)上癮的開(kāi)發(fā)人員來(lái)說(shuō),它就像他們的游樂(lè)場(chǎng)。而對(duì)于另一類人來(lái)說(shuō),微服務(wù)架構(gòu)是“一個(gè)架構(gòu)搞定一切”,它可以消除任何軟件系統(tǒng)的復(fù)雜性。而筆者認(rèn)為,微服務(wù)架構(gòu)和單一體系架構(gòu)可以互為補(bǔ)充。對(duì)于長(zhǎng)期而言都很精簡(jiǎn)的應(yīng)用程序,單一體系架構(gòu)可能更為合適。而另一方面,對(duì)于大型而且復(fù)雜的應(yīng)用程序,或者有可能變得大而復(fù)雜的應(yīng)用程序,微服務(wù)架構(gòu)這一解決方案更加有效?,F(xiàn)今的軟件開(kāi)發(fā)通常是十分龐大的工程,以至于微服務(wù)架構(gòu)和單一體系架構(gòu)可以實(shí)現(xiàn)共存,就像SQL和NoSQL數(shù)據(jù)庫(kù)的共存一樣。 10個(gè)最佳實(shí)踐 正確地設(shè)計(jì)微服務(wù)架構(gòu)是一項(xiàng)非常困難和具有挑戰(zhàn)性的工作。和為所有問(wèn)題提供一勞永逸解決方案的單一體系架構(gòu)相反,微服務(wù)體系架構(gòu)針對(duì)不同的問(wèn)題提供了不同的解決方案。如果選擇了錯(cuò)誤的解決方案,那么微服務(wù)架構(gòu)就將是一顆定時(shí)炸彈,注定要引爆。一個(gè)設(shè)計(jì)有缺陷的微服務(wù)架構(gòu)比單一體系架構(gòu)更加糟糕。為微服務(wù)架構(gòu)定義一組最佳實(shí)踐也是一項(xiàng)挑戰(zhàn)。我看過(guò)一些會(huì)議演講,其中有一些著名和受人尊敬的軟件工程師們提出過(guò)一些關(guān)于微服務(wù)架構(gòu)的最佳實(shí)踐,但結(jié)果適得其反。 在本文中,我將提出一些微服務(wù)架構(gòu)的最佳實(shí)踐,這些實(shí)踐將有助于開(kāi)發(fā)有效的微服務(wù)應(yīng)用程序,其中目標(biāo)項(xiàng)目的預(yù)期壽命將會(huì)超過(guò)6個(gè)月,團(tuán)隊(duì)規(guī)模從中等到大型(6名以上的開(kāi)發(fā)人員)。 在這里,我也將列出一些關(guān)于微服務(wù)架構(gòu)最佳實(shí)踐的帖子供大家參考,例如Martin Fowler撰寫的《微服務(wù)架構(gòu)的特征》、Chris Richardson撰寫的《微服務(wù)模式》、和Tony Mauro撰寫的《在Netflix上采用微服務(wù):架構(gòu)設(shè)計(jì)的若干教訓(xùn)》。也有一些很棒的演講,例如Stefan Tilkov的演講《微服務(wù)模式和反模式》,David Schmitz的演講《應(yīng)對(duì)微服務(wù)嚴(yán)重失敗的10條技巧》,Sam Newman的演講《微服務(wù)原理》。此外,我還編寫了一份精心挑選的書(shū)籍清單,這些書(shū)籍對(duì)于理解微服務(wù)架構(gòu)設(shè)計(jì)的以下10個(gè)最佳實(shí)踐必不可少: 1. 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD:Domain-Driven Design) 開(kāi)發(fā)微服務(wù)的最重要的挑戰(zhàn)是將一個(gè)大型、復(fù)雜的應(yīng)用程序拆分成小型、自主管理的、并且可以獨(dú)立部署的模塊。 如果應(yīng)用程序沒(méi)有以正確的方式進(jìn)行拆分,那么產(chǎn)生的微服務(wù)將會(huì)是緊密耦合的,它們將會(huì)同時(shí)具有單一體系架構(gòu)的所有缺點(diǎn)和微服務(wù)的所有復(fù)雜性,這種架構(gòu)被稱為分布式單一體系架構(gòu)(Distributed Monolith)。 幸運(yùn)的是,在這方面已經(jīng)有一些可以大有幫助的解決方案。Eric Evans是一名軟件工程顧問(wèn),他曾在不同公司中多次遇到有關(guān)業(yè)務(wù)應(yīng)用程序中復(fù)雜性的問(wèn)題,并在2004年出版的書(shū)籍《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì):解決軟件核心的復(fù)雜性》中總結(jié)了一些寶貴的見(jiàn)解。該書(shū)概述了以下三個(gè)核心概念: 軟件開(kāi)發(fā)團(tuán)隊(duì)?wèi)?yīng)與業(yè)務(wù)部門或領(lǐng)域?qū)<颐芮泻献鳌?/p> 架構(gòu)師/開(kāi)發(fā)人員和領(lǐng)域?qū)<覒?yīng)首先進(jìn)行戰(zhàn)略設(shè)計(jì):找到有界的上下文和相關(guān)的核心域、通用語(yǔ)言、子域、上下文映射等等。 然后,架構(gòu)師/開(kāi)發(fā)人員應(yīng)進(jìn)行戰(zhàn)術(shù)設(shè)計(jì),將核心領(lǐng)域分解為細(xì)粒度的構(gòu)建塊:如實(shí)體(Entity)、值對(duì)象(Value Object)、聚合(Aggregate)、聚合根(Aggregate Root)等等。 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的詳細(xì)討論超出了這篇文章的范圍,但是你可以閱讀Eric Evans撰寫的關(guān)于領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的早期著作:《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì):解決軟件核心的復(fù)雜性》(藍(lán)皮書(shū)),或者閱讀更現(xiàn)代一點(diǎn)的,由Vaughn Vernon撰寫的《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)之實(shí)施》一書(shū)(紅皮書(shū))。 如果將一個(gè)大型系統(tǒng)劃分為核心域和子域,然后將核心域和子域映射到一個(gè)或多個(gè)微服務(wù)上,那么就可以得到理想的松耦合微服務(wù)。 2. 微服務(wù)的數(shù)據(jù)庫(kù) 將復(fù)雜的應(yīng)用程序拆分為微服務(wù)模塊后,下一個(gè)挑戰(zhàn)就出現(xiàn)了 -- 如何處理數(shù)據(jù)庫(kù)?是否應(yīng)該在微服務(wù)之間共享數(shù)據(jù)庫(kù)?這個(gè)問(wèn)題的答案是把雙刃劍,有利有弊。 一方面,微服務(wù)之間共享數(shù)據(jù)庫(kù),會(huì)導(dǎo)致微服務(wù)之間的強(qiáng)耦合,這與微服務(wù)體系架構(gòu)的目標(biāo)正好相反。即使數(shù)據(jù)庫(kù)中出現(xiàn)微小變化,也需要團(tuán)隊(duì)之間的同步操作。 而且,在一個(gè)服務(wù)中管理事務(wù)和鎖定數(shù)據(jù)庫(kù)就已經(jīng)足夠具有挑戰(zhàn)性了,管理多個(gè)分布式微服務(wù)之間的事務(wù)和鎖定更是一項(xiàng)極其艱巨的任務(wù)。 另一方面,如果每個(gè)微服務(wù)都有自己的數(shù)據(jù)庫(kù)/私有表,那么在微服務(wù)之間交換數(shù)據(jù)就相當(dāng)于打開(kāi)了潘多拉的魔盒。 因此,許多著名的軟件工程師都主張?jiān)谖⒎?wù)之間共享數(shù)據(jù)庫(kù),以此作為一種實(shí)用的解決方案。但是,在我看來(lái),微服務(wù)本質(zhì)上是一個(gè)可持續(xù)和長(zhǎng)期的軟件開(kāi)發(fā)過(guò)程,因此,每個(gè)微服務(wù)都應(yīng)該有自己的數(shù)據(jù)庫(kù)(或私有表)。 3. 微前端 不幸的是,大多數(shù)后端開(kāi)發(fā)人員都對(duì)前端開(kāi)發(fā)都有一個(gè)過(guò)時(shí)的看法,認(rèn)為前端開(kāi)發(fā)很簡(jiǎn)單。 由于大多數(shù)軟件架構(gòu)師都是后臺(tái)開(kāi)發(fā)人員,所以他們很少考慮前端,在架構(gòu)設(shè)計(jì)中往往忽略前端。在微服務(wù)項(xiàng)目中,后端及其和數(shù)據(jù)庫(kù)的交互通常會(huì)很好地模塊化,但前端只有一個(gè)單一整體。 在最好的情況下,開(kāi)發(fā)人員會(huì)考慮使用最熱門的SPA(React,Angular,Vue)之一來(lái)開(kāi)發(fā)這個(gè)單一的前端。這種方法的主要問(wèn)題在于前端的單一架構(gòu)和后端的單一架構(gòu)一樣的糟糕,正如我之前所描述的。 此外,當(dāng)前端需要適應(yīng)瀏覽器的變化而進(jìn)行現(xiàn)代化更新時(shí),它就需要進(jìn)行一場(chǎng)大爆炸式的更新(這就是為什么許多公司仍然使用過(guò)時(shí)的Angular 1框架的原因)。 前端簡(jiǎn)單但功能非常強(qiáng)大,并提供了固有的嵌入。開(kāi)發(fā)基于SPA的微前端有很多方法:使用iFrame、Web組件或借助Elements(Angular/React)。 4. 持續(xù)交付 微服務(wù)架構(gòu)的關(guān)鍵USP(獨(dú)特賣點(diǎn))之一是每個(gè)微服務(wù)都可以獨(dú)立部署。如果你有一個(gè)由100個(gè)微服務(wù)組成的系統(tǒng),并且只需要更改一個(gè)微服務(wù),那么你可以只更新一個(gè)而無(wú)需更改其他99個(gè)微服務(wù)。 但是,在沒(méi)有任何自動(dòng)化系統(tǒng)(DevOps,CI/CD)幫助的情況下獨(dú)立部署100個(gè)微服務(wù)是一項(xiàng)艱巨的任務(wù)。要充分利用此微服務(wù)功能,需要采用CI/CD和DevOps系統(tǒng)。使用不帶CI/CD、DevOps系統(tǒng)的微服務(wù)架構(gòu),就像購(gòu)買最新的保時(shí)捷,然后用手剎來(lái)駕駛它。 難怪微服務(wù)專家Martin Fowler將CI/CD列為使用微服務(wù)體系架構(gòu)的三個(gè)先決條件之一。 5. 可觀察性 微服務(wù)架構(gòu)的一個(gè)主要缺點(diǎn)是,軟件開(kāi)發(fā)變得簡(jiǎn)單,但卻犧牲了運(yùn)營(yíng)。對(duì)于單一架構(gòu)來(lái)說(shuō),對(duì)應(yīng)用程序的監(jiān)控要簡(jiǎn)單得多。 但是由于很多微服務(wù)在容器上運(yùn)行,整個(gè)系統(tǒng)的可觀察性變得非常關(guān)鍵和復(fù)雜。 甚至日志記錄也變得復(fù)雜,無(wú)法將許多容器/機(jī)器中的日志聚合到一個(gè)中心位置。幸運(yùn)的是,現(xiàn)在市場(chǎng)上已經(jīng)有很多企業(yè)級(jí)解決方案。例如,ELK/Splunk可以提供微服務(wù)日志記錄。 Prometheus/App Dynamics可以提供行業(yè)級(jí)的監(jiān)控。微服務(wù)領(lǐng)域中另一個(gè)非常關(guān)鍵的可觀察性工具是Tracing。 通常,對(duì)微服務(wù)的一個(gè)API請(qǐng)求會(huì)導(dǎo)致對(duì)其他微服務(wù)的多個(gè)級(jí)聯(lián)調(diào)用。要分析微服務(wù)系統(tǒng)的延遲,必須測(cè)量每個(gè)微服務(wù)的延遲。Zipkin/Jaeger為微服務(wù)提供了出色的跟蹤支持。 6. 統(tǒng)一技術(shù)棧 微服務(wù)架構(gòu)要求,對(duì)于一個(gè)微服務(wù),需要采用最適合該微服務(wù)的編程語(yǔ)言和框架。這句話不應(yīng)該只從字面上理解。 有時(shí),微服務(wù)可能需要一個(gè)新的技術(shù)堆棧,例如對(duì)于CPU繁重/高性能的任務(wù),可以選擇像C / Rust這樣的編程語(yǔ)言。如果一個(gè)微服務(wù)是為機(jī)器學(xué)習(xí)服務(wù),那么Python也許是一個(gè)更好的選擇。 但是,如果沒(méi)有充分的理由使用不同的編程語(yǔ)言/框架,可能會(huì)導(dǎo)致太多的編程語(yǔ)言和框架, 而沒(méi)有帶來(lái)任何實(shí)質(zhì)性的好處。想象一下, 如果一個(gè)微服務(wù)是用Spring Boot Kotlin React MySQL開(kāi)發(fā)的,另一個(gè)是用JakartaEE Java Angular PostgreSQL開(kāi)發(fā)的,再另一個(gè)又是用Scala Play Framework VueJS Oracle開(kāi)發(fā)的,那么維護(hù)這么多不同的編程語(yǔ)言、數(shù)據(jù)庫(kù)和框架需要付出巨大的努力,但收獲卻很小。 7.異步通信 微服務(wù)架構(gòu)中最具挑戰(zhàn)性的設(shè)計(jì)決策之一是服務(wù)之間如何通信和共享數(shù)據(jù)。當(dāng)每個(gè)微服務(wù)都有自己的數(shù)據(jù)存儲(chǔ)時(shí),這一點(diǎn)尤為重要。 通常,一個(gè)微服務(wù)可以單獨(dú)存在,但卻不能單獨(dú)實(shí)現(xiàn)所有的業(yè)務(wù)目標(biāo)。所有的微服務(wù)需要協(xié)同工作才能實(shí)現(xiàn)業(yè)務(wù)目標(biāo)。 而為了協(xié)同工作,它們需要交換數(shù)據(jù)或觸發(fā)其他微服務(wù)來(lái)完成任務(wù)。微服務(wù)之間最簡(jiǎn)單和最常見(jiàn)的通信方式是通過(guò)同步REST API,這種方法很實(shí)用,但不是長(zhǎng)久之計(jì)。 如果服務(wù)A調(diào)用服務(wù)B,服務(wù)B調(diào)用服務(wù)C,服務(wù)C同步調(diào)用服務(wù)D,那么延遲就會(huì)疊加。此外,由于微服務(wù)大多是分布式系統(tǒng),它們可能會(huì)失敗。 所以同步微服務(wù)經(jīng)常會(huì)導(dǎo)致故障級(jí)聯(lián)(failure cascading),即一個(gè)服務(wù)中的故障可能會(huì)導(dǎo)致其他服務(wù)中的故障。 微服務(wù)之間的同步通信還會(huì)導(dǎo)致微服務(wù)之間的緊密耦合。對(duì)于長(zhǎng)期解決方案,微服務(wù)應(yīng)該采用異步通信。 微服務(wù)之間的異步通信有多種方式:通過(guò)消息隊(duì)列(如Kafka)、通過(guò)異步REST(ATOM)或者CQRS。 8. 微服務(wù)優(yōu)先 許多專家認(rèn)為,對(duì)于新建項(xiàng)目,最好從松散耦合的單一體系架構(gòu)開(kāi)始,因?yàn)槲⒎?wù)體系架構(gòu)需要大量的初始工作來(lái)設(shè)置運(yùn)營(yíng)。在他們看來(lái),一旦項(xiàng)目足夠成熟,“精心”設(shè)計(jì)的單一架構(gòu)可以很容易地轉(zhuǎn)換為微服務(wù)架構(gòu)。然而,在我看來(lái),這種方法在大多數(shù)情況下都會(huì)失敗。在實(shí)際應(yīng)用中,單一架構(gòu)系統(tǒng)內(nèi)部的模塊將緊密耦合,這會(huì)導(dǎo)致很難將其轉(zhuǎn)換為微服務(wù)架構(gòu)。另外,一旦應(yīng)用程序投入生產(chǎn),在不中斷應(yīng)用程序的情況下,將其轉(zhuǎn)換為微服務(wù)將更加困難。所以,如果最終有計(jì)劃使用微服務(wù)架構(gòu),我的建議是從一開(kāi)始就采用微服務(wù)架構(gòu)。 9. 基于庫(kù)的基礎(chǔ)設(shè)施 在微服務(wù)軟件開(kāi)發(fā)的早期,Netflix主要使用Java編程來(lái)開(kāi)發(fā)微服務(wù)。他們還開(kāi)發(fā)了許多庫(kù)(Netflix OSS Stack,包括Hystrix、Zuul)。 許多公司效仿Netflix,開(kāi)始使用Netflix OSS庫(kù)。后來(lái),許多公司(包括Netflix)發(fā)現(xiàn),由于Java的體積龐大和冷啟動(dòng)問(wèn)題,它并不是開(kāi)發(fā)微服務(wù)的合適語(yǔ)言。 Netflix后來(lái)轉(zhuǎn)向Polyglot微服務(wù)范式,并決定不再進(jìn)一步開(kāi)發(fā)Netflix OSS,這導(dǎo)致追隨Netflix的公司陷入困境。 因此,與其在特定語(yǔ)言庫(kù)(如基于Java的Netflix OSS)上投入巨資,不如使用框架(如服務(wù)網(wǎng)格、API網(wǎng)關(guān))更為明智。 10. 組織考慮 大約50年前(1967年),梅爾文·康威(Melvin Conway)觀察到公司的軟件架構(gòu)受到組織結(jié)構(gòu)的制約(康威定律)。 雖然這項(xiàng)觀察已有50年歷史,但麻省理工學(xué)院和哈佛商學(xué)院最近發(fā)現(xiàn),該定律在現(xiàn)代仍然有效。如果一個(gè)組織計(jì)劃開(kāi)發(fā)微服務(wù)架構(gòu),那么它應(yīng)該相應(yīng)地確定團(tuán)隊(duì)規(guī)模(兩個(gè)“美式”披薩團(tuán)隊(duì)的大?。?人或9人)。 另外,團(tuán)隊(duì)?wèi)?yīng)該是跨職能的,理想情況下應(yīng)該擁有前端/后端開(kāi)發(fā)人員、運(yùn)維人員和測(cè)試人員。只有在高層管理者也相應(yīng)地改變他們的觀點(diǎn)和愿景的情況下,微服務(wù)架構(gòu)才能發(fā)揮作用。 原文:https:///effective-microservices-10-best-practices-c6e4ba0c6ee2 本文為 CSDN 翻譯,轉(zhuǎn)載請(qǐng)注明來(lái)源出處。 【End】 熱 文推 薦 |
|
|
來(lái)自: yi321yi > 《系統(tǒng)》