在過去的幾年中,我已經(jīng)完成了對處于數(shù)字化轉(zhuǎn)型過程中的多個產(chǎn)品團隊的架構(gòu)審查。 大多數(shù)團隊都在按照微服務(wù)架構(gòu)構(gòu)建產(chǎn)品。 他們有使用基于微服務(wù)的體系結(jié)構(gòu)的所有正確意圖-更快的開發(fā),更好的可伸縮性,更小的獨立團隊,獨立的部署,使用正確的技術(shù)來完成工作,等等。但是,我經(jīng)常發(fā)現(xiàn)團隊在微服務(wù)方面苦苦掙扎。 他們未能充分利用微服務(wù)的優(yōu)勢。 在這篇文章中,我將分享我認為團隊在微服務(wù)方面苦苦掙扎的原因。
對于微服務(wù)新手,我建議閱讀Martin Fowler的微服務(wù)文章。 我喜歡本文中提到的微服務(wù)架構(gòu)定義。
微服務(wù)架構(gòu)風格是一種將單個應(yīng)用程序開發(fā)為一組小型服務(wù)的方法,每個小型服務(wù)都在自己的進程中運行并與輕量級機制(通常是HTTP資源API)進行通信。 這些服務(wù)圍繞業(yè)務(wù)功能構(gòu)建,并且可以由全自動部署機制獨立部署。 這些服務(wù)的集中管理幾乎沒有,可以用不同的編程語言編寫并使用不同的數(shù)據(jù)存儲技術(shù)。
原因1:管理層低估了開發(fā)微服務(wù)的復(fù)雜性
我曾與多個對微服務(wù)非??春玫目蛻粢黄鸸ぷ?。 對他們來說,微服務(wù)是解決所有問題的靈丹妙藥。 在討論中,我發(fā)現(xiàn)大多數(shù)團隊及其管理層低估了微服務(wù)開發(fā)的復(fù)雜性。
要開發(fā)微服務(wù),開發(fā)人員需要高效的本地環(huán)境設(shè)置。
隨著系統(tǒng)中服務(wù)的增加,變得越來越難在一臺計算機上運行應(yīng)用程序的子集。 當您使用消耗相對較多內(nèi)存的語言(例如Java)構(gòu)建應(yīng)用程序時,尤其會發(fā)生這種情況。
以下是與本地開發(fā)設(shè)置有關(guān)的要點。
· 本地開發(fā)的第一個重要方面是好的開發(fā)機器。 我發(fā)現(xiàn)大多數(shù)組織都很難使用所有最新和最先進的技術(shù),但是他們不想替換性能低下的Windows開發(fā)機器。 開發(fā)人員受其開發(fā)機器的限制。 我已經(jīng)看到開發(fā)人員使用VDI映像或配置較差的機器來構(gòu)建基于微服務(wù)的系統(tǒng)。 這降低了他們的生產(chǎn)力,他們無法完全應(yīng)用自己。 使用劣質(zhì)的開發(fā)機器的副作用是,開發(fā)人員無法獲得快速反饋。 如果您知道必須等待幾分鐘才能運行集成測試套件,那么您寧愿不用編寫更多內(nèi)容也不會增加工作量。 不良的開發(fā)機器會導(dǎo)致不良的開發(fā)實踐。
· 一旦有了您的開發(fā)人員,合理的機器就可以工作。 接下來的事情是確保所有服務(wù)都使用構(gòu)建工具。 您應(yīng)該能夠在無需太多配置的情況下在一臺新計算機上構(gòu)建整個應(yīng)用程序。 以我在微服務(wù)方面的經(jīng)驗,即使使用根構(gòu)建腳本也可以構(gòu)建整個應(yīng)用程序,這很有幫助。
· 下一個重點是使開發(fā)人員能夠輕松地在系統(tǒng)上運行應(yīng)用程序的某些部分。 您應(yīng)該使用多個docker-compose文件來啟動配置了所有端口和卷的不同服務(wù)。
· 接下來,如果您使用的是Kubernetes之類的容器編排工具,則應(yīng)該投資于Telepresence之類的工具,該工具可以輕松調(diào)試Kubernetes集群中的應(yīng)用程序。
如果組織不了解微服務(wù)的開發(fā)復(fù)雜性,那么團隊速度會隨著時間的推移而下降。
原因2:沒有將庫和工具更新到最新版本的過程
在我的評論中,我發(fā)現(xiàn)新平臺已經(jīng)成為歷史。 團隊無法確保依賴關(guān)系保持最新狀態(tài),或者數(shù)據(jù)庫等工具是否為最新版本。 因此,兩年前開始的現(xiàn)代化工作如今已經(jīng)有數(shù)月的技術(shù)債務(wù)。
幾年前,許多團隊開始將Spring Cloud Netflix OSS項目用于微服務(wù)。 他們使用的是Kubernetes之類的容器編排工具,但由于它們是從Netflix OSS開始的,因此并未使用Kubernetes提供的所有功能。 當Kubernetes內(nèi)置服務(wù)發(fā)現(xiàn)時,他們?nèi)詫ureka用作服務(wù)發(fā)現(xiàn)。 此外,借助Istio這樣的服務(wù)網(wǎng)格,您可以擺脫Netflix OSS提供的大多數(shù)功能。 這有助于降低復(fù)雜性,并將很多交叉問題轉(zhuǎn)移到平臺上。
要記住的另一點是,要使所有服務(wù)的依賴項版本保持同步。 我最近在幫助一個使用Spring Boot構(gòu)建微服務(wù)的客戶。 在過去的兩年中,他們已經(jīng)構(gòu)建了20多個Spring Boot服務(wù)。 在他們的環(huán)境中,他們使用的Spring Boot版本范圍從1.5到2.1。 這意味著當有人設(shè)置他們的機器時,他們必須下載多個版本的Spring Boot。 此外,他們?nèi)鄙僮?.5以來在Spring Boot中所做的許多改進。
我們的建議是組織應(yīng)在積壓的訂單中為這些升級創(chuàng)建技術(shù)債務(wù)項目。 這些技術(shù)債務(wù)項目應(yīng)在架構(gòu)委員會會議上進行討論并定期解決。 在我的上一個項目中,我們每三個月設(shè)置一個星期的沖刺,以將所有依賴項更新到最新版本。
此外,團隊應(yīng)該花時間在升級工具上,例如數(shù)據(jù)庫,消息隊列和緩存,以升級到最新版本。
原因3:將共享服務(wù)用于本地開發(fā)
由于本地開發(fā)不佳,大多數(shù)團隊開始依靠共享環(huán)境提供關(guān)鍵服務(wù)。 開發(fā)人員機器中的第一件事就是數(shù)據(jù)庫。 大多數(shù)年輕的開發(fā)人員都沒有意識到基于共享數(shù)據(jù)庫的開發(fā)是邪惡的。 以下是我在共享數(shù)據(jù)庫中遇到的主要問題:
· 團隊成員必須建立工作的社會契約,以避免最后的作家勝出問題。 開發(fā)人員可以清除另一位開發(fā)人員為其工作編寫的數(shù)據(jù)。 這種工作方式既痛苦又容易失敗。 遲早這會咬傷團隊。
· 開發(fā)人員擔心實驗會影響他們的其他團隊成員。 我們都知道,更好的學(xué)習(xí)方法是實驗和快速反饋。 有了共享數(shù)據(jù)庫,就可以進行實驗了。 我們需要進行實驗以提出數(shù)據(jù)庫架構(gòu)并執(zhí)行性能調(diào)整之類的任務(wù)。
· 另一個副作用是很難單獨測試更改。 您的集成測試變得不穩(wěn)定。 從而進一步降低了顯影速度。
· 共享數(shù)據(jù)庫必須像寵物一樣對待,因為您不希望共享數(shù)據(jù)庫的狀態(tài)不一致且不可預(yù)測。 您可能有一個開發(fā)人員想要在表為空但其他人需要表具有記錄的情況下測試邊緣情況。
· 僅共享數(shù)據(jù)庫具有系統(tǒng)正常工作所需的所有數(shù)據(jù)。 隨著時間的流逝,團隊成員失去了更改的可追溯性,因此沒人知道他們?nèi)绾螐?fù)制他們計算機上相同的設(shè)置。 唯一的方法是獲取完整的數(shù)據(jù)庫轉(zhuǎn)儲并使用它。
· 未連接到網(wǎng)絡(luò)時很難工作。 通勤時間長或乘飛機時,通常會發(fā)生這種情況。
數(shù)據(jù)庫只是共享服務(wù)的一個示例,但它也可以是消息傳遞隊列,像Redis這樣的集中式緩存或服務(wù)可以改變的任何其他服務(wù)。
解決此問題的最佳方法是使開發(fā)人員可以輕松地在其計算機上運行數(shù)據(jù)庫(作為docker容器),并投資創(chuàng)建SQL腳本來設(shè)置架構(gòu)和初始主數(shù)據(jù)。 這些SQL腳本應(yīng)保留在版本控制中,并像其他任何代碼一樣進行維護。
原因4:版本控制托管平臺缺乏可見性
我正在與一個在其版本控制系統(tǒng)中具有1000多個存儲庫的客戶端一起工作。 他們正在使用Gitlab版本控制平臺。 他們有5個產(chǎn)品,每個產(chǎn)品都由多個微服務(wù)組成。 我問他們的第一個問題是幫助我們了解哪些服務(wù)及其各自的代碼存儲庫是產(chǎn)品A的一部分。他們的首席架構(gòu)師不得不花一天的時間弄清楚構(gòu)成產(chǎn)品A的所有存儲庫。 不知道她是否涵蓋了所有服務(wù)。
解決此問題的最佳方法是從一開始就以某種方式對微服務(wù)進行分組,以使您始終對產(chǎn)品生態(tài)系統(tǒng)具有可見性。 Gitlab提供了一種創(chuàng)建組,然后在其中創(chuàng)建項目存儲庫的方法。 Github沒有組功能,因此您可以使用主題或命名約定來實現(xiàn)它。
我個人更喜歡mono repos,因為我發(fā)現(xiàn)它們真的很方便。 我遇到的大多數(shù)開發(fā)人員都將其視為反模式。 我同意Dan Lua的帖子,他在文章中提到了mono repo的以下好處
*簡化的組織
*簡化的依賴關(guān)系
*工具
*跨項目變更
原因5:沒有明確的服務(wù)定義
大多數(shù)團隊都不知道應(yīng)該將什么視為服務(wù)。 關(guān)于實際上構(gòu)成單個微服務(wù)的東西有很多困惑和困惑。 讓我們舉一個例子,您的應(yīng)用程序具有類似插件的架構(gòu),您將在其中與多個第三方服務(wù)集成。 每個集成都應(yīng)該是微服務(wù)嗎? 我已經(jīng)看到多個團隊正在為每個集成創(chuàng)建一個微服務(wù)。 隨著集成數(shù)量的增加,這很快變得難以管理。 這些服務(wù)通常太小,以至于它們作為單獨的進程運行會增加更多的開銷。
我認為擁有少量大型服務(wù)總比擁有太多小型服務(wù)好。我將首先創(chuàng)建一個對業(yè)務(wù)組織中整個部門建模的服務(wù)。這也符合DDD。我將一個域分為子域和有界上下文。有界上下文表示公司內(nèi)部的部門,例如財務(wù)和市場營銷。您可能認為這可能會導(dǎo)致大型微服務(wù),這是正確的。但是,以我的經(jīng)驗來看,將單片重構(gòu)為微服務(wù)總是比反之容易。隨著您獲得更多的知識,您可以轉(zhuǎn)向代表較小關(guān)注點的細粒度微服務(wù)。您可以應(yīng)用"單一責任原則"來了解您的微服務(wù)是否變得太大而做太多的事情。然后,您可以將其分解為較小的獨立服務(wù)。任何服務(wù)都不應(yīng)直接與另一個服務(wù)的數(shù)據(jù)庫對話。他們只能通過已發(fā)布的合同進行溝通。您可以閱讀Microservices.io網(wǎng)站上提到的有關(guān)按子域模式分解的更多信息。
我也遵循后端文檔中提到的建議。 該建議可以幫助限制服務(wù)之間的通信,這是基于微服務(wù)的系統(tǒng)性能低下的首要原因。
如果兩條信息相互依賴,則它們應(yīng)屬于一臺服務(wù)器。 換句話說,服務(wù)的自然邊界應(yīng)該是其數(shù)據(jù)的自然邊界。
原因6:沒有明確的代碼重用策略
我正在與一個客戶一起工作,該客戶已在其所有基于Java的微服務(wù)中復(fù)制了四個與特定問題相關(guān)的Java文件。 因此,如果在該代碼中發(fā)現(xiàn)錯誤,則需要將其應(yīng)用到所有地方。 我們都知道,在時間壓力下,我們會錯過將更改應(yīng)用于一項或多項服務(wù)的機會。 這將浪費更多時間并增加挫敗感。
開發(fā)團隊并不了解正確的事情。 但是,組織的結(jié)構(gòu)化方式人們總是默認使用簡單且容易出錯的做事方式。
正確的方法是使用工件管理器(如Bintray或Nexus)并在其中發(fā)布依賴項。 然后,每個微服務(wù)都應(yīng)依賴該庫。 您需要構(gòu)建工具,以便在發(fā)布新版本的庫時,應(yīng)更新并重新部署所有微服務(wù)。
使用微服務(wù)并不意味著您不應(yīng)使用迄今為止對我們有用的最佳實踐。 您需要在工具上進行投資,以使其易于升級微服務(wù),從而使人類不必這樣做。
在沒有適當工具和自動化的情況下使用微服務(wù)是災(zāi)難的根源。
原因7:多種語言編程
我找到了使用多種編程語言,多個數(shù)據(jù)庫,多個緩存的團隊,這是工作的最佳工具。 所有這些都在項目的初始階段起作用,但是當您的產(chǎn)品投入生產(chǎn)時,這些選擇就開始顯示出它們的真實色彩。 諸如我們在構(gòu)建Java Spring Boot應(yīng)用程序之類的原因,但我們意識到Java占用了更多內(nèi)存,并且性能很差,因此我們決定切換到Node.js。 在上一個任務(wù)中,我向團隊解釋說他們的推理能力很弱。
· Node.js的性能優(yōu)于Java。 如果您有基于IO的工作負載,則Node.js通常會表現(xiàn)更好。 Java在任何計算密集型工作負載上均勝過node.js。 通過使用響應(yīng)式范例,Java for IO工作負載可以具有更好的性能。 Spring Boot Reactor在IO工作負載方面的性能與Node.js相當。
· Node.js消耗的內(nèi)存少于Java。 這部分是正確的,因為Node.js應(yīng)用程序通常使用的內(nèi)存少于Java。 Java Spring Boot應(yīng)用程序并不像大多數(shù)人想象的那樣糟糕。 我在其中一個Spring Boot Java Microservice上進行了負載測試,并且內(nèi)存消耗仍然少于1 GB。 您可以通過OpenJVM,限制對類路徑的依賴性以及通過調(diào)整默認JVM參數(shù)來優(yōu)化Java內(nèi)存利用率。 另外,Java中的Spring Boot替代品還有Micronaut和Quarkus等,它們消耗的內(nèi)存等于Node.js。
· Node.js比Java更高效。 這取決于開發(fā)人員編寫代碼。 帶有靜態(tài)類型和靜態(tài)分析工具的Java可以幫助在開發(fā)生命周期的早期發(fā)現(xiàn)問題。
大多數(shù)時候,這全都取決于上下文。 如果您的開發(fā)人員不成熟,則無論使用哪種編程語言,您都將開發(fā)出不良的產(chǎn)品。
我建議組織發(fā)布團隊可以使用的語言列表。 我認為2–3是個好數(shù)字。 另外,列出為什么應(yīng)使用一種語言代替另一種語言的原因。
選擇語言之前,應(yīng)考慮以下多種原因:
· 輕松找到成熟的企業(yè)軟件開發(fā)人員有多容易?
· 重新培訓(xùn)開發(fā)人員使用新技術(shù)有多容易? 我們發(fā)現(xiàn)Java開發(fā)人員可以相對輕松地學(xué)習(xí)Golang。
· 最初團隊之外的開發(fā)人員可以多么容易地貢獻,傳輸和維護他人編寫的代碼?
· 就工具和庫而言,生態(tài)系統(tǒng)的成熟程度如何?
這不僅限于編程語言。 這也適用于數(shù)據(jù)庫。 如果您的系統(tǒng)中已經(jīng)有MongoDB,那么為什么要在生態(tài)系統(tǒng)中使用ArangoDB? 它們都主要是文檔數(shù)據(jù)庫。
始終考慮使用多種技術(shù)的維護和操作方面。
原因8:人們依賴性
這并非特定于微服務(wù),但在微服務(wù)生態(tài)系統(tǒng)中變得更加普遍。 原因是大多數(shù)團隊專注于他們的特定服務(wù),因此他們不了解完整的生態(tài)系統(tǒng)。 在與不同客戶的合作中,我發(fā)現(xiàn)只有一小部分了解整體情況的建筑師。 但是,這些架構(gòu)師的問題在于他們在日常活動中不活躍,因此對開發(fā)的影響有限。
我認為最好的辦法是確保所有團隊在架構(gòu)小組中只有一個代表性的部分,以便他們可以使團隊與整體架構(gòu)團隊的路線圖和目標保持一致。 要成為一個成熟的組織,您需要投資建立輕量級的治理。
原因9:缺少文檔
過去幾年中與我們互動的大多數(shù)組織都在文檔方面苦苦掙扎。 大多數(shù)開發(fā)人員和架構(gòu)師要么不編寫文檔,要么他們編寫的文檔沒有用。 即使他們想寫,他們也不知道應(yīng)該如何記錄其體系結(jié)構(gòu)。
至少我們應(yīng)該記錄以下內(nèi)容:
· 設(shè)計文件
· C4模型中的上下文和容器圖
· 以架構(gòu)決策記錄的形式跟蹤關(guān)鍵架構(gòu)決策
· 開發(fā)人員入門指南
我建議所有文檔都保留在版本控制系統(tǒng)中。
原因10:功能超過平臺成熟度
我在其他方面簡要地談到了這個原因,但是我認為值得一提的是它的首要原因。 微服務(wù)比傳統(tǒng)的單片應(yīng)用程序更為復(fù)雜,因為您正在構(gòu)建具有許多活動部件的分布式系統(tǒng)。 大多數(shù)開發(fā)人員尚未理解系統(tǒng)的不同故障模式。 大多數(shù)微服務(wù)在構(gòu)建時都考慮了一條愉快的路。 因此,如果您的管理層只想早于專注于功能,那么您將失敗。 在弱平臺上構(gòu)建的功能無法帶來價值。
組織需要進入平臺心態(tài)。 平臺心態(tài)不僅意味著使用容器和Kubernetes。 它們是解決方案的一部分,但本身并不是完整的解決方案。 您需要考慮分布式跟蹤,可觀察性,混亂測試,函數(shù)調(diào)用與網(wǎng)絡(luò)調(diào)用,服務(wù)到服務(wù)通信的安全服務(wù),可調(diào)試性等。這需要大量的精力和投資來建立合適的平臺和工具團隊。
如果您是一家資源有限的初創(chuàng)公司,我的建議是重新考慮您的微服務(wù)策略。 請了解您正在進入什么。
原因11:缺乏自動化測試
大多數(shù)團隊都知道自動化測試對產(chǎn)品的整體質(zhì)量有多重要,但他們?nèi)匀粵]有做到。 微服務(wù)架構(gòu)為在何處以及如何進行測試提供了更多選擇。 如果您不進行全面的自動化測試,那么您將嚴重失敗。
關(guān)于這一點,我不會寫太多,因為網(wǎng)絡(luò)上許多其他人已經(jīng)討論過這一點。 我從Martin Fowler網(wǎng)站上發(fā)布的Microservices測試文章中獲取的下圖討論了基于Microservices的系統(tǒng)的測試金字塔。
Microservices Test Pyramid
-
API
+關(guān)注
關(guān)注
2文章
1503瀏覽量
62128 -
微服務(wù)
+關(guān)注
關(guān)注
0文章
137瀏覽量
7363
發(fā)布評論請先 登錄
相關(guān)推薦
評論