这些年我对微服务的理解
Monolith、SOA、DDD、The?two-pizza?rule、分庫分表這些概念跟微服務(wù)有啥關(guān)系,你知道嗎?這篇文章記錄我的理解,分享給大家。
微服務(wù)(micro service),個(gè)人感覺也就近幾年才吵起來的概念,記得退回去四五年(2014年),那時(shí)候大家還談?wù)揝OA(service orentied architecture)比較多。在SOA之前,一個(gè)軟件系統(tǒng)大多都是前后端不分離的monolith的架構(gòu),通常采用比如說spring mvc、java SSH (spring/structs/hibernate)、.net framework mvc、.net framework web form等技術(shù)方案實(shí)現(xiàn)。
在計(jì)算機(jī)這個(gè)領(lǐng)域,好像每隔一段時(shí)間總會(huì)有一些概念被炒作起來,就像近幾年在炒作的微服務(wù)、云原生、人工智能AI、區(qū)塊鏈等,大家都在努力抓住這些風(fēng)口,聽說現(xiàn)在有的大學(xué)里面,學(xué)生不發(fā)AI相關(guān)的論文就不讓畢業(yè),我想這或許是python近兩年在有的語言排行榜超過java成為榜首的原因之一吧。
關(guān)于微服務(wù)架構(gòu)的概念,網(wǎng)上有很多介紹,大家可以自行搜索。這里推薦一個(gè)業(yè)界比較有名的網(wǎng)址,Martin Fowler的個(gè)人網(wǎng)址:https://martinfowler.com/articles/microservices.html。Martin fowler是微服務(wù)領(lǐng)域的一個(gè)專家,它有很多關(guān)于微服務(wù)方面的研究,有興趣的童鞋可以去他的個(gè)人網(wǎng)址上查閱相關(guān)資料。
那么,如何構(gòu)建一個(gè)微服務(wù)架構(gòu)的應(yīng)用呢?基于之前的經(jīng)驗(yàn),我的總結(jié)如下:
一、掌握好拆分微服務(wù)的粒度,使得每個(gè)微服務(wù)相對(duì)獨(dú)立,但又是整個(gè)業(yè)務(wù)流程的一部分。怎樣才能掌握好這個(gè)粒度呢?我覺得有一種說法挺有道理:從業(yè)務(wù)角度,可以遵循DDD(domain driven development),即領(lǐng)域建模,按照具體的業(yè)務(wù)流程來劃分;從團(tuán)隊(duì)組織角度,一個(gè)團(tuán)隊(duì)負(fù)責(zé)一個(gè)或多個(gè)微服務(wù),團(tuán)隊(duì)大小遵循“The two-pizza rule”。
二、系統(tǒng)的整體設(shè)計(jì)需要遵循12 factors原則。
三、從系統(tǒng)實(shí)現(xiàn)的角度來看,考慮下面這些點(diǎn):
API?Gateway
Service?Registry?and?Discovery?-?Eureka
Circuit?Breaker?-?Hystrix
Fault?Tolerant?-?Hystrix
Message?Broker?-?RabbitMQ
Database?-?Postgres
Logging?and?Tracing?-?ELK
Authorization?and?Authentication?-?OpenID/SAML/OAuth/JWT
Secure?Credential?Store?-?Vault
Security?and?Audit
CI/CD?-?Jenkins
Monitoring?-?Grafana
Container?Runtime?-?Docker/CloudFoundry/Kuberntes
Scaling?-?Vertical?scaling/Horizontal?scaling
Proxy?and?Load?Balancer?-?nginx
Multi-Tenancy
此外,下面是我對(duì)微服務(wù)相關(guān)話題的一些思考:
一、微服務(wù)火了之后,業(yè)界一直有這樣一個(gè)問題:微服務(wù)和SOA的區(qū)別到底是什么?
我個(gè)人的理解是這樣的,SOA出現(xiàn)的背景大約是前后端不分離的monolith應(yīng)用時(shí)代,為了解決各個(gè)應(yīng)用系統(tǒng)之間的集成,于是就出現(xiàn)了SOA(service oriented architecture),意即面向服務(wù)的架構(gòu),idea就是把應(yīng)用系統(tǒng)當(dāng)成一個(gè)服務(wù)來設(shè)計(jì),這樣外部系統(tǒng)就可以很好的來消費(fèi)這個(gè)服務(wù),記得那時(shí)候把服務(wù)暴露出來的常用做法就是SOAP;而微服務(wù)出現(xiàn)的背景是,SOA本質(zhì)上大多還是monolith架構(gòu),即是單體應(yīng)用,為了解決單體應(yīng)用很重的問題,出現(xiàn)了微服務(wù)。所以SOA是第一階段,服務(wù)主要面向系統(tǒng)外部集成;而微服務(wù)則是第二階段,服務(wù)不但面向系統(tǒng)外部,同時(shí)也面向系統(tǒng)內(nèi)部。
二、微服務(wù)和monolith的比較,下面是我個(gè)人的看法:
微服務(wù)開發(fā)效率更高,環(huán)境setup簡單,build/checkout/run更快,ut/it 時(shí)間更短。各個(gè)微服務(wù)職責(zé)分離,邊界清晰,有利于cross team開發(fā),特別是對(duì)于跨location的協(xié)作開發(fā),優(yōu)勢(shì)更加明顯。記得之前有一個(gè)monolith的項(xiàng)目,代碼總共幾百萬行,從git上拉下來都要幾十分鐘,build也很慢,ut/it需要跑非常長時(shí)間,開發(fā)效率很低,同時(shí)也非常不利于實(shí)現(xiàn)CI/CD。
從擴(kuò)展性方面來講,微服務(wù)既可以水平擴(kuò)展,也可以垂直擴(kuò)展。而monolith只可以水平擴(kuò)展。
有人說monolith可以利用數(shù)據(jù)庫事務(wù),保證強(qiáng)一致性,而微服務(wù)則不能保證強(qiáng)一致性,通常只能保證最終一致性,這是monolith的一個(gè)優(yōu)點(diǎn)。我覺得這個(gè)點(diǎn)需要辯證的來看,因?yàn)閺?qiáng)一致性,有時(shí)候也會(huì)帶來一些性能問題,比如事務(wù)很大且高并發(fā)的情況,數(shù)據(jù)庫容易成為瓶頸,最終導(dǎo)致吞吐量太低。同時(shí),正如我之前寫的一篇文章(關(guān)于分布式系統(tǒng)數(shù)據(jù)一致性的那些事),現(xiàn)實(shí)生活中也不可能有一個(gè)大而全的系統(tǒng)可以cover所以的場景,并且用事務(wù)保證強(qiáng)一致性。一個(gè)典型的例子,銀行轉(zhuǎn)賬往往需要強(qiáng)一致性,單個(gè)銀行系統(tǒng)可以用數(shù)據(jù)庫事務(wù)實(shí)現(xiàn),但是跨銀行系統(tǒng)轉(zhuǎn)賬就不可能利用單機(jī)數(shù)據(jù)庫事務(wù),因?yàn)椴煌y行系統(tǒng)都是自己的數(shù)據(jù)庫,所以即使是銀行系統(tǒng)并不能保證強(qiáng)一致性。之前一個(gè)同事說他就親身經(jīng)歷過一次銀行系統(tǒng)短時(shí)不一致的情況:他跨行取錢,錢被扣了,但是錢沒吐出來,最后是去柜臺(tái)人工處理才解決。
三、微服務(wù)到底是選擇共享數(shù)據(jù)庫還是獨(dú)立數(shù)據(jù)庫?下面是我個(gè)人的看法:
如果是共享數(shù)據(jù)庫的話,仍然類似于單體設(shè)計(jì)(數(shù)據(jù)庫層面的單體設(shè)計(jì)),數(shù)據(jù)庫層只能水平擴(kuò)展,?容易成為瓶頸,比如說鎖資源占有、死鎖、 DB層面緊耦合導(dǎo)致開發(fā)互相影響等。原則上,對(duì)于微服務(wù)系統(tǒng),應(yīng)該只有API是不同微服務(wù)之間的contract,如果采用共享數(shù)據(jù)庫,就又引入了另外一個(gè)層面的contract,不容易維護(hù),當(dāng)有其他團(tuán)隊(duì)的人改了數(shù)據(jù)庫,容易導(dǎo)致意想不到的錯(cuò)。
有人說采用共享數(shù)據(jù)庫,做報(bào)表更方便。是的,如果是共享數(shù)據(jù)庫,報(bào)表生成可以直接基于數(shù)據(jù)庫來做join等操作,而如果是獨(dú)立數(shù)據(jù)庫,直接基于數(shù)據(jù)庫的join就不行。但是,采用共享數(shù)據(jù)庫也并不意味著報(bào)表方便。一般來說報(bào)表屬于OLAP操作,而業(yè)務(wù)邏輯屬于OLTP操作,理論上講,列級(jí)數(shù)據(jù)庫更適合OLAP操作,而行級(jí)數(shù)據(jù)庫更適合OLTP操作,如果報(bào)表這類OLAP操作和業(yè)務(wù)邏輯OLTP操作同用一個(gè)數(shù)據(jù)庫的話,大量的OLAP操作會(huì)影響OLTP業(yè)務(wù)處理,所以,這兩類操作分開用各自合適的數(shù)據(jù)庫,才能互不影響并且利用不同數(shù)據(jù)庫的優(yōu)勢(shì)。記得,退回去幾年(2014年),大數(shù)據(jù)還比較火,大家都在炒作這個(gè)概念,Hadoop、HBase、Spark、HANA等就是那時(shí)候的產(chǎn)物,其實(shí)個(gè)人理解大數(shù)據(jù)就是拿來做OLAP操作的。
四、分庫分表和微服務(wù)的關(guān)系?
當(dāng)一個(gè)系統(tǒng)數(shù)據(jù)量上去了,往往都需要考慮分庫分表的事情。因?yàn)橐坏?shù)據(jù)量級(jí)上去了,數(shù)據(jù)庫很容易就成為瓶頸。所以,怎么實(shí)現(xiàn)分庫分表呢?其實(shí),微服務(wù)本身就是一個(gè)很好的分庫分表的實(shí)現(xiàn)。首先,每個(gè)微服務(wù)獨(dú)立數(shù)據(jù)庫就是一個(gè)層面的分庫,不同微服務(wù)相關(guān)的業(yè)務(wù)數(shù)據(jù)存在單獨(dú)的數(shù)據(jù)庫,可以一定程度緩解共享數(shù)據(jù)庫的瓶頸。其次,一個(gè)SaaS系統(tǒng)往往需要考慮多租戶,一種多租戶實(shí)現(xiàn)策略就是:每個(gè)租戶擁有自己的獨(dú)立數(shù)據(jù)庫,不同租戶的數(shù)據(jù)就被存在各自獨(dú)立的數(shù)據(jù)庫,這樣又是一個(gè)層面的分庫。其實(shí)分庫的本質(zhì)也就是通過一種哈希算法,把數(shù)據(jù)分散到不同的數(shù)據(jù)庫實(shí)例上,以達(dá)到負(fù)載均衡的作用。另外,有時(shí)候通過分庫仍然會(huì)存在一些表數(shù)據(jù)量太大的問題,比如訂單表,當(dāng)數(shù)據(jù)量太大的時(shí)候,其讀寫操作的性能往往會(huì)急劇下降,這時(shí)候就需要做分表了。其實(shí),個(gè)人覺得分庫某些時(shí)候也是一種分表,除此之外,還有一些其它策略,比如說,我們可以把比較老的數(shù)據(jù)存到另外一張表去,就像一些電商平臺(tái),用戶默認(rèn)只能看最近三個(gè)月的訂單等。
五、遷移monolith應(yīng)用到微服務(wù)架構(gòu)
如果我們開發(fā)一個(gè)系統(tǒng),一開始選型就是微服務(wù),這樣很容易。但是,有時(shí)候我們需要把一個(gè)非常龐大的monolith應(yīng)用遷移到微服務(wù)架構(gòu),這往往不是一件容易的事情。一般怎么做呢?我們需要從多個(gè)層面考慮:技術(shù)層面,首先需要仔細(xì)思考怎么拆分微服務(wù),有時(shí)候這會(huì)很難,因?yàn)閷?duì)于一個(gè)龐大的monolith應(yīng)用,之前的實(shí)現(xiàn)各個(gè)模塊之間往往耦合得非常緊;其次需要把之前的數(shù)據(jù)褲拆分為每個(gè)微服務(wù)獨(dú)立的數(shù)據(jù)庫,這也會(huì)很難,因?yàn)樵趺磳?shí)現(xiàn)數(shù)據(jù)遷移需要仔細(xì)考慮,可以參考我之前寫過的一篇文章(如何不宕機(jī)實(shí)現(xiàn)數(shù)據(jù)庫遷移)。另外,團(tuán)隊(duì)層面也需要考慮很多,比如說團(tuán)隊(duì)的組織結(jié)構(gòu)可能需要調(diào)整、團(tuán)隊(duì)成員的mindset需要buildup等。
最后,最近各大云廠商都在大力炒作cloud native,我查看了一些關(guān)于相關(guān)介紹,感覺其實(shí)它和微服務(wù)就是換湯不換藥,其實(shí)就是基于微服務(wù)的概念,然后加了一些容器編排的概念。See https://jimmysong.io/kubernetes-handbook/cloud-native/cloud-native-definition.html。
References
https://martinfowler.com/articles/microservices.html#HowBigIsAMicroservice
https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/ddd-oriented-microservice
https://12factor.net/
https://jimmysong.io/kubernetes-handbook/cloud-native/cloud-native-definition.html
https://www.oreilly.com/library/view/microservices-antipatterns-and/9781492042716/ch04.html
總結(jié)
以上是生活随笔為你收集整理的这些年我对微服务的理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对比Java和.NET多线程编程
- 下一篇: .NET Core开发实战(第21课:中