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