.NET分布式框架 | Orleans 知多少
引言
公司物聯(lián)網(wǎng)項(xiàng)目集成Orleans以支持高并發(fā)的分布式業(yè)務(wù),對(duì)于Orleans也是第一次接觸,本文就分享下個(gè)人對(duì)Orleans的理解。
這里先拋出自己的觀點(diǎn):Orleans 是一個(gè)支持有狀態(tài)云生應(yīng)用/服務(wù)水平伸縮的基于Virtual Actor 模型的.NET分布式框架。
下面我會(huì)從以下幾個(gè)關(guān)鍵點(diǎn),進(jìn)行闡述:
云生應(yīng)用的挑戰(zhàn)
何為有狀態(tài)/無(wú)狀態(tài)
什么是 Actor 模型
什么是 Virtual Actor 模型
云生應(yīng)用的挑戰(zhàn)
在講云生應(yīng)用之前,我們來(lái)先講講傳統(tǒng)應(yīng)用,對(duì)于傳統(tǒng)應(yīng)用常用的三層結(jié)構(gòu)如下圖所示。
隨著業(yè)務(wù)的發(fā)展,數(shù)據(jù)庫(kù)層通常存在瓶頸,為了緩解數(shù)據(jù)庫(kù)的壓力,一般會(huì)優(yōu)先考慮增加一層緩存層。
而隨著業(yè)務(wù)的繼續(xù)發(fā)展,高并發(fā)、大數(shù)據(jù)量的應(yīng)用場(chǎng)景逐漸凸顯。如果繼續(xù)在單體應(yīng)用的基礎(chǔ)上進(jìn)行擴(kuò)展,能做的無(wú)非是增加消息隊(duì)列、異步、讀寫分離等機(jī)制進(jìn)行性能優(yōu)化。總體而言,優(yōu)化空間不大,但應(yīng)用的整體復(fù)雜度卻隨著引入的新的技術(shù)框架而迅速增加,對(duì)于應(yīng)用的維護(hù),是一個(gè)潛在的定時(shí)炸彈。
這個(gè)時(shí)候你可能會(huì)想,既然單體應(yīng)用單機(jī)部署不能滿足需求,我可以做集群啊。通過(guò)將單體應(yīng)用按照分層結(jié)構(gòu)進(jìn)行縱向分離,將數(shù)據(jù)庫(kù)從應(yīng)用服務(wù)器分離,將緩存從應(yīng)用服務(wù)器分離。這樣就可以對(duì)分離的各個(gè)部分進(jìn)行分別部署,再借助負(fù)載均衡完成集群效應(yīng)。到這一步,你的應(yīng)用應(yīng)該能撐一段時(shí)間了。
這個(gè)時(shí)候,如果回到業(yè)務(wù)本身去分析,對(duì)于一個(gè)復(fù)雜應(yīng)用來(lái)說(shuō),通常的性能瓶頸就是幾個(gè)核心服務(wù)上。如果能夠?qū)Υ嬖谛阅芷款i的服務(wù)進(jìn)行伸縮,既能大大提高應(yīng)用的整體可用性又能提高資源的利用率。那怎么做呢?服務(wù)拆分。
云生應(yīng)用就是服務(wù)拆分的結(jié)果,云生應(yīng)用最大的特點(diǎn)就是:
并行:是指同一時(shí)刻能夠處理多個(gè)任務(wù)。這無(wú)可厚非,云生應(yīng)用以多個(gè)服務(wù)形式提供服務(wù),自然是支持并行的。
分布式:是指一個(gè)應(yīng)用/服務(wù)多次部署,以應(yīng)對(duì)高并發(fā),提升應(yīng)用/服務(wù)的整體性能。
或者簡(jiǎn)單來(lái)說(shuō),云生應(yīng)用通過(guò)服務(wù)拆分支持服務(wù)并行,同時(shí)各個(gè)服務(wù)能夠快速伸縮以提升系統(tǒng)吞吐量來(lái)應(yīng)對(duì)高并發(fā)的業(yè)務(wù)場(chǎng)景。
雖然通過(guò)服務(wù)拆分簡(jiǎn)化了整個(gè)應(yīng)用的業(yè)務(wù)復(fù)雜度,但是實(shí)現(xiàn)的技術(shù)復(fù)雜度卻只增不減。
有狀態(tài) Vs 無(wú)狀態(tài)
轉(zhuǎn)向云生應(yīng)用我們面對(duì)的第一個(gè)難題就是:如何進(jìn)行服務(wù)拆分,才能確保其能分布式部署,或者說(shuō)是水平伸縮?!
有經(jīng)驗(yàn)的同學(xué),可能會(huì)立馬想到,要將應(yīng)用/服務(wù)設(shè)計(jì)為無(wú)狀態(tài)的。但是這里我要向你討教幾個(gè)問(wèn)題:
這個(gè)狀態(tài)是指什么?
何為有狀態(tài)?
何為無(wú)狀態(tài)?
大家不妨先停下來(lái)思考一下。(歡迎大家在評(píng)論中闡述不同觀點(diǎn)。)
這里,我嘗試從以下兩個(gè)角度來(lái)談下自己的看法:
1. 對(duì)象
面向?qū)ο缶幊虖?qiáng)調(diào)的是對(duì)現(xiàn)實(shí)事物的抽象和封裝。通過(guò)對(duì)事物狀態(tài)和行為進(jìn)行抽象然后封裝為對(duì)象(類),其中狀態(tài)封裝為類的屬性、字段,將行為封裝為類的方法。這個(gè)時(shí)候得到的對(duì)象是沒(méi)有生命力的,因?yàn)樗举|(zhì)是一個(gè)抽象的結(jié)果。只有在程序運(yùn)行中對(duì)類進(jìn)行實(shí)例化得到一個(gè)對(duì)象的實(shí)例時(shí),才可以說(shuō)這個(gè)實(shí)例對(duì)象是有狀態(tài)和行為的,因?yàn)檫@個(gè)狀態(tài)和行為是其獨(dú)自持有的,這是一個(gè)非常核心的條件。獨(dú)自持有,換句話說(shuō),就是非共享成員。獨(dú)自持有非共享的成員就可以說(shuō)這個(gè)對(duì)象實(shí)例是有狀態(tài)的嗎?這里面你就要看清狀態(tài)和有狀態(tài)的區(qū)別!舉個(gè)簡(jiǎn)單例子,大街上你看到一大叔開著豪車,你覺(jué)得他很富有。“開著豪車”是你即時(shí)看到的狀態(tài)屬性。“富有”是你的狀態(tài)斷言。但這個(gè)狀態(tài)斷言是一個(gè)假設(shè),畢竟可能是借的嘛。怎樣才能斷定“富有”就是這位大叔擁有的狀態(tài)呢?很簡(jiǎn)單,假設(shè)一年365天你天天見到他開豪車,那基本八九不離十了。
所以,如果認(rèn)定一個(gè)對(duì)象是否有狀態(tài),還要看其狀態(tài)屬性是否持久化!
如果你同意這個(gè)觀點(diǎn),那么哪天你看我騎個(gè)共享單車,氣喘吁吁從你面前經(jīng)過(guò),就不要簡(jiǎn)單認(rèn)為我是苦逼工薪族。畢竟我也是身價(jià)上千萬(wàn),只是偶爾騎個(gè)車鍛煉鍛煉。(身價(jià)上千萬(wàn),昨晚夢(mèng)到的。)
所以,從對(duì)象角度看,一個(gè)對(duì)象是否有狀態(tài)的充分必要條件是:
對(duì)象已實(shí)例化(處于運(yùn)行時(shí))
擁有非共享的狀態(tài)屬性
狀態(tài)持久化
那問(wèn)題來(lái)了,我們經(jīng)常寫的類創(chuàng)建的實(shí)例,是有狀態(tài)的嗎?
2. 應(yīng)用
基于上面的總結(jié),我們?cè)賮?lái)從應(yīng)用的角度來(lái)看分析這個(gè)問(wèn)題。
那應(yīng)用的狀態(tài)和行為是什么?首先,只有運(yùn)行中的應(yīng)用才有狀態(tài)和行為。基于這個(gè)前提,個(gè)人理解運(yùn)行時(shí)應(yīng)用的狀態(tài)是應(yīng)用持有的數(shù)據(jù),行為是應(yīng)用提供的功能。那應(yīng)用的有無(wú)/無(wú)狀態(tài)界定就要看運(yùn)行時(shí)應(yīng)用持有的數(shù)據(jù)能否持久化。
以簡(jiǎn)單的Web分層應(yīng)用舉例?。從邏輯架構(gòu)上來(lái)講應(yīng)用一般分為三層,表示層、業(yè)務(wù)層和數(shù)據(jù)訪問(wèn)層。上層進(jìn)行狀態(tài)行為的封裝,數(shù)據(jù)層提供數(shù)據(jù)的持久化。所以從整體的角度來(lái)看,其是一個(gè)有狀態(tài)的應(yīng)用。但單獨(dú)來(lái)看,我們不能對(duì)每一層進(jìn)行有/無(wú)狀態(tài)的界定。第一,每一層不能單獨(dú)運(yùn)行;第二,分層的目的是為了職責(zé)的隔離,每一層負(fù)責(zé)相應(yīng)職責(zé)的抽象和封裝,其輸出的是類文件,是對(duì)象的集合,沒(méi)有生命力。
那從物理架構(gòu)上來(lái)講,Web應(yīng)用可以分開兩個(gè)部分進(jìn)行部署:Web實(shí)例和MySQL實(shí)例。也就是說(shuō)應(yīng)用和數(shù)據(jù)庫(kù)是可以分開部署的。這個(gè)時(shí)候Web實(shí)例就是無(wú)狀態(tài)的。那我們一般常說(shuō)的無(wú)狀態(tài)服務(wù)其實(shí)是就是從這個(gè)拆分的角度來(lái)說(shuō)的。
Actor 模型
理清完服務(wù)拆分的核心問(wèn)題后,我們不得不來(lái)處理第二個(gè)棘手的問(wèn)題:如何解決云生應(yīng)用高并發(fā)的應(yīng)用場(chǎng)景呢?那首先我們需要明確處理高并發(fā)的難點(diǎn)在哪?第一個(gè)是高性能,第二個(gè)就是:資源競(jìng)爭(zhēng)導(dǎo)致的數(shù)據(jù)一致性問(wèn)題。對(duì)于第一個(gè)難點(diǎn),通過(guò)水平擴(kuò)展服務(wù)可以化解;對(duì)于第二個(gè)難點(diǎn),一般就是采用鎖機(jī)制,而對(duì)于云生分布式的應(yīng)用場(chǎng)景下,處理手段就更加復(fù)雜,可能需要使用分布式鎖,而這種做法,大大降低了應(yīng)用的整體響應(yīng)性能。那有沒(méi)有更好的解決方案,既兼顧性能又可以確保數(shù)據(jù)一致性呢?
有,借助Actor模型。
簡(jiǎn)單來(lái)講:Actor模型 = 狀態(tài) + 行為 + 消息。一個(gè)應(yīng)用/服務(wù)由多個(gè)Actor組成,每個(gè)Actor都是一個(gè)獨(dú)立的運(yùn)行單元,擁有隔離的運(yùn)行空間,在隔離的空間內(nèi),其有獨(dú)立的狀態(tài)和行為,不被外界干預(yù),Actor之間通過(guò)消息進(jìn)行交互,而同一時(shí)刻,每個(gè)Actor只能被單個(gè)線程執(zhí)行,這樣既有效避免了數(shù)據(jù)共享和并發(fā)問(wèn)題,又確保了應(yīng)用的伸縮性。
另外Actor基于事件驅(qū)動(dòng)模型進(jìn)行異步通信,性能良好。且位置透明,無(wú)論Actor是在本機(jī)亦或是在集群中的其他機(jī)器,都可以直接進(jìn)行透明調(diào)用。
因此Actor模型賦予了應(yīng)用/服務(wù)的生命力(有狀態(tài))、高并發(fā)的處理能力和彈性伸縮能力。
Virtual Actor 模型 與 Orleans
對(duì)于Actor模型,業(yè)界已經(jīng)有系列的實(shí)現(xiàn)框架,比如Erlang、Akka。然而Actor模型作為一個(gè)偏底層的技術(shù)框架,對(duì)于開發(fā)者來(lái)說(shuō),需要有一定分布式應(yīng)用的開發(fā)經(jīng)驗(yàn),才能用好Actor(包括Actor的生命周期管理,狀態(tài)管理等等)。為了進(jìn)一步簡(jiǎn)化分布式編程,微軟的研究人員引入了 Virtual Actor 模型概念,簡(jiǎn)單來(lái)講Virtual Actor模型是對(duì)Actor模型的進(jìn)一步封裝和抽象。其與Actor模型的最大的區(qū)別在于,Actor的物理實(shí)例完全被抽象出來(lái),并由Virtual Actor所在的運(yùn)行時(shí)自動(dòng)管理。
Orleans 就是作為一款面向.NET的Virtual Actor模型的實(shí)現(xiàn)框架,提供了開發(fā)者友好的編程方式,簡(jiǎn)化了分布式應(yīng)用的開發(fā)成本。在Orleans中Virtual Actor由Grain來(lái)體現(xiàn)。
Orleans中核心優(yōu)勢(shì):開發(fā)效率高、透明可伸縮。
開發(fā)效率高具體表現(xiàn)為:
面向?qū)ο蟮木幊谭妒饺?shí)現(xiàn)Grain
Grain單線程執(zhí)行
Grain透明實(shí)例化:換句話說(shuō),應(yīng)用無(wú)需關(guān)注Actor實(shí)例的創(chuàng)建、銷毀,可以直接調(diào)用Actor提供的方法。Actor的生命周期由Virtual Actor 運(yùn)行時(shí)進(jìn)行管理,類似GC,可以把Actor理解為完全托管的狀態(tài)。
Grain位置透明:Actor之間通過(guò)持有彼此的邏輯引用(非實(shí)例引用)進(jìn)行相互調(diào)用,而不需要知道Actor所處的實(shí)際位置。
Grain狀態(tài)透明存儲(chǔ)
異常的自動(dòng)傳播
透明可伸縮體現(xiàn)為:
應(yīng)用狀態(tài)的隱式細(xì)粒度劃分
自適應(yīng)的資源管理:Grain的生命周期完全由Orleans 運(yùn)行時(shí)托管。
多路通信:Grain的位置透明,Grain之間通過(guò)一組固定的TCP鏈接進(jìn)行多路復(fù)用來(lái)進(jìn)行消息傳遞。
高效調(diào)度
顯式異步
最后
這篇文章,就簡(jiǎn)單寫到這里,對(duì)于Orleans的詳細(xì)介紹后續(xù)會(huì)結(jié)合實(shí)際項(xiàng)目輸出更系統(tǒng)的應(yīng)用細(xì)節(jié),下次再見。
總結(jié)
以上是生活随笔為你收集整理的.NET分布式框架 | Orleans 知多少的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 从零开始实现ASP.NET Core M
- 下一篇: ASP.NET Core on K8S学