Newbe.Claptrap-一套以“事件溯源”和“Actor模式”作为基本理论的服务端开发框架...
本文是關(guān)于 Newbe.Claptrap 項目主體內(nèi)容的介紹,讀者可以通過這篇文章,大體了解項目內(nèi)容。
輪子源于需求
隨著互聯(lián)網(wǎng)應(yīng)用的蓬勃發(fā)展,相關(guān)的技術(shù)理論和實現(xiàn)手段也在被不斷創(chuàng)造出來。諸如 “云原生架構(gòu)”、“微服務(wù)架構(gòu)”、“DevOps” 等一系列關(guān)鍵詞越來越多的出現(xiàn)在工程師的視野之中。總結(jié)來看,這些新理論和新技術(shù)的出現(xiàn),都是為了解決互聯(lián)網(wǎng)應(yīng)用中出現(xiàn)的一些技術(shù)痛點:
更高的容量擴展性要求。在商業(yè)成功的基礎(chǔ)前提下,互聯(lián)網(wǎng)應(yīng)用的用戶數(shù)量、系統(tǒng)壓力和硬件設(shè)備數(shù)量等方面都會隨著時間的推移出現(xiàn)明顯的增長。這就對應(yīng)用本身的容量可擴展性提出了要求。這種容量可擴展性通常被描述為 “應(yīng)用需要支持水平擴展”。
更高的系統(tǒng)穩(wěn)定性要求。應(yīng)用程序能夠不間斷運行,確保商業(yè)活動的持續(xù)進展,這是任何與這個應(yīng)用系統(tǒng)相關(guān)的人員都希望見到的。但是要做到這點,通常來說是十分困難的。而現(xiàn)今的互聯(lián)網(wǎng)應(yīng)用在面對諸多同類競爭者的情況下,如果在這方面做得不夠健全,那么很可能會失去一部分用戶的青睞。
更高的功能擴展性要求。“擁抱變化”,當(dāng)人們提到 “敏捷項目管理” 相關(guān)的內(nèi)容時,都會涉及到的一個詞語。這個詞語充分體現(xiàn)了當(dāng)今的互聯(lián)網(wǎng)應(yīng)用若要成功,在功能性上做到出彩做到成功是多么的重要。也從一個側(cè)面體現(xiàn)了當(dāng)前互聯(lián)網(wǎng)環(huán)境下產(chǎn)品需求的多變。而作為系統(tǒng)工程師,在應(yīng)用建立之初就應(yīng)該考慮這點。
更高的開發(fā)易用度要求。這里所屬的開發(fā)易用度是指,在應(yīng)用系統(tǒng)自身在進行開發(fā)時的難易程度。要做到越易于開發(fā),在應(yīng)用自身的代碼結(jié)構(gòu),可測試性,可部署性上都需要作出相應(yīng)的努力。
更高的性能要求。這里提到的性能要求,是特指在系統(tǒng)容量增加時的性能要求。避免系統(tǒng)的單點性能問題,讓應(yīng)用系統(tǒng)具備可水平擴展的特性。通常來說,在性能出現(xiàn)問題時,若可以通過增加物理設(shè)備來解決問題,通常來說是最為簡單的辦法。而在不同的系統(tǒng)容量之下,系統(tǒng)性能的優(yōu)化方案通常是不同的。因此結(jié)合應(yīng)用場景進行技術(shù)方案的選型一直都是系統(tǒng)工程師所需要考慮的問題。
本項目,就是基于以上這些系統(tǒng)功能特性要求所總結(jié)出來的一套開發(fā)框架。這其中包含了相關(guān)的理論基石、開發(fā)類庫和技術(shù)規(guī)約。
世界上本也不存在 “銀彈”。一套框架解決不了所有問題。—— 不愿意透露姓名的月落
從需求出發(fā)
在講解分布式系統(tǒng)時,常常會用到 “賬號轉(zhuǎn)賬” 這個簡單的業(yè)務(wù)場景來配合描述。這里闡述一下這個業(yè)務(wù)場景。
假設(shè)我們需要建設(shè)一個具備賬號體系的業(yè)務(wù)系統(tǒng)。每個賬號都有余額。現(xiàn)在需要執(zhí)行一次轉(zhuǎn)賬操作,將賬號 A 的余額中的 300 劃轉(zhuǎn)給賬號 B。另外,基于上節(jié)的基本要求,我們在實現(xiàn)這個場景時,需要考慮以下這些內(nèi)容:
需要應(yīng)對系統(tǒng)容量的激增。應(yīng)用初期可能只有 1000 個初始用戶。由于應(yīng)用推廣效果良好以及機器人賬號的涌入,用戶數(shù)量實現(xiàn)了在一個月內(nèi)實現(xiàn)了三個數(shù)量級的攀升,也就是增長到了百萬級別。
需要考慮系統(tǒng)的穩(wěn)定性和可恢復(fù)性。盡可能減少系統(tǒng)整體的平均故障時間,即使出現(xiàn)系統(tǒng)故障也應(yīng)該是盡可能易于恢復(fù)的。也就是,要避免出現(xiàn)單點故障。
需要考慮業(yè)務(wù)的可擴展性。后續(xù)可能需要增加一些業(yè)務(wù)邏輯:按照賬戶等級限制日轉(zhuǎn)賬額、轉(zhuǎn)賬成功后進行短信通知、轉(zhuǎn)賬支持一定額度的免密轉(zhuǎn)賬、特定的賬號實現(xiàn) “T+1” 到賬。
需要考慮代碼的可測試性。系統(tǒng)的業(yè)務(wù)代碼和系統(tǒng)代碼能夠良好的分離,能夠通過單元測試的手段初步驗證業(yè)務(wù)代碼和系統(tǒng)代碼的正確性和性能。
輪子的理論
本節(jié)將介紹一些和本框架緊密結(jié)合的理論內(nèi)容,便于讀者在后續(xù)的過程中理解本框架的工作過程。
Actor 模式
Actor 模式是一種并發(fā)編程模型。通過這種編程模型的應(yīng)用可以很好的解決一些系統(tǒng)的并發(fā)問題。這里所提到的并發(fā)問題是指計算機對同一數(shù)據(jù)進行邏輯處理時,可能由于存在多個同時發(fā)起的請求可能導(dǎo)致數(shù)據(jù)出現(xiàn)不正確的問題。這個問題在進行多線程編程時一定會遇到的問題。舉個簡單的例子,假如在不加同步鎖的情況下,使用 100 個線程并發(fā)對內(nèi)存中的一個?int?變量執(zhí)行?++?操作。那么最終這個變量的結(jié)果往往小于 100。此處 Actor 模式是如何避免此問題的。
首先,為了便于理解,讀者在此處可以將 Actor 認為是一個對象。在面向?qū)ο蟮恼Z言(Java、C# 等)當(dāng)中,可以認為 Actor 就是通過?new?關(guān)鍵詞創(chuàng)建出來的對象。不過這個對象有一些特別的特性:
擁有屬于自身的狀態(tài)。對象都可以擁有自身的屬性,這是面向?qū)ο笳Z言基本都具備的功能。在 Actor 模式中,這些屬性都被統(tǒng)稱為?Actor的狀態(tài)(State)。Actor 的狀態(tài)由 Actor 自身進行維護。
這就強調(diào)了兩點:
第一、Actor 的狀態(tài)只能由自身進行改變,若要從外部改變 Actor 的狀態(tài),只能通過調(diào)用 Actor 才能改變。
第二、Actor 的狀態(tài)只在 Actor 內(nèi)部進行維護,不與當(dāng)前 Actor 之外的任何對象共享。這里說的不共享也是強調(diào)其不能通過外部某個屬性的改變而導(dǎo)致 Actor 內(nèi)部狀態(tài)的變化。這點主要是為了區(qū)別于一些具備 “對象引用” 語言特性的編程語言而言的。例如:在 C# 的?class?的?public?屬性,假如是引用類型,那么在外部獲得這個?class?之后是可以改變?class?中的屬性的。但是這在 Actor 模式當(dāng)中是不被允許的。
不過從 Actor 內(nèi)部讀取數(shù)據(jù)到外部,這仍然是允許的。
單線程。Actor 通常同一時間只能接受一個調(diào)用。這里所述的線程不完全是指計算機中的線程,是為了凸顯 “Actor 同一時間只能處理一個請求的特性” 而使用的詞語。假如當(dāng)前 Actor 正在接受一個調(diào)用,那么剩余的調(diào)用都會阻塞,直到調(diào)用結(jié)束,下一個請求才允許被進入。這其實類似于一個同步鎖的機制。通過這種機制就避免了對 Actor 內(nèi)部狀態(tài)進行修改時,存在并發(fā)問題的可能。具體一點說明:如果使用 100 個線程對一個 Actor 進行并發(fā)調(diào)用,讓 Actor 對狀態(tài)中的一個?int?變量進行?++?操作。最終這個狀態(tài)的數(shù)值一定是 100。
不過單線程也不是絕對的,在不存在并發(fā)問題的請求情況下,允許并發(fā)處理。例如讀取 Actor 中的狀態(tài),這通常不會有并發(fā)問題,那么此時就允許進行并發(fā)操作。
讀到 Actor 單線程特性時,通常讀者會考慮到這是否會導(dǎo)致 Actor 本身處理過慢而產(chǎn)生性能問題呢?關(guān)于這點,希望讀者繼續(xù)持有這個問題往后閱讀,尋找答案。
事件溯源模式
事件溯源模式是一種軟件設(shè)計思路。這種設(shè)計思路通常與傳統(tǒng)的采用增刪查改(CRUD)為主的系統(tǒng)設(shè)計思路相區(qū)別。CRUD 應(yīng)用通常存在一些局限性:
通常來說 CRUD 應(yīng)用會采用直接操作數(shù)據(jù)存儲的做法。這樣的實現(xiàn)方式可能會由于對數(shù)據(jù)庫優(yōu)化不足而導(dǎo)致性能瓶頸,并且這種做法會較難實現(xiàn)應(yīng)用伸縮。
在特定的領(lǐng)域通常存在一些數(shù)據(jù)需要注意對并發(fā)問題進行處理,以防止數(shù)據(jù)更新的錯誤。這通常需要引入 “鎖”、“事務(wù)” 等相關(guān)的技術(shù)來避免此類問題。但這樣又有可能引發(fā)性能上的損失。
除非增加額外的審計手段,否則通常來說數(shù)據(jù)的變更歷史是不可追蹤的。因為數(shù)據(jù)存儲中通常保存的是數(shù)據(jù)最終的狀態(tài)。
與 CRUD 做法對比,事件溯源則從設(shè)計上避免了上述描述的局限性。接下來圍繞上文中提到的 “轉(zhuǎn)賬” 業(yè)務(wù)場景簡述事件溯源的基礎(chǔ)工作方式。
采用 CRUD 的方法實現(xiàn) “轉(zhuǎn)賬”。
采用事件溯源的方式實現(xiàn) “轉(zhuǎn)賬”。
圖片過大,原圖鏈接:https://www.newbe.pro/images/20190227-001.gif
如上圖所示,通過事件溯源模式將轉(zhuǎn)賬業(yè)務(wù)涉及的余額變動采用事件的方式進行存儲。同樣也實現(xiàn)了業(yè)務(wù)本身,而這樣卻帶來了一些好處:
通過事件,可以還原出賬號任何階段的余額,這就一定程度實現(xiàn)了對賬號余額的跟蹤。
由于兩個賬號的事件是獨立處理的。因此,兩個賬號的處理速度不會相互影響。例如,賬號 B 的轉(zhuǎn)入可能由于需要額外的處理,稍有延遲,但賬號 A 仍然可以的轉(zhuǎn)出。
可以通過訂閱事件來做一些業(yè)務(wù)的異步處理。例如:更新數(shù)據(jù)庫中的統(tǒng)計數(shù)據(jù),發(fā)送短信通知等其他的一些異步操作。
當(dāng)然引入事件溯源模式之后也就引入了事件溯源相關(guān)的一些技術(shù)問題。例如:事件所消耗的存儲可能較為巨大;不得不應(yīng)用最終一致性;事件具備不可變性,重構(gòu)時可能較為困難等。相關(guān)的這些問題在一些文章中會有較為細致的說明。讀者可以閱讀后續(xù)的延伸閱讀內(nèi)容,進而進行了解與評估。
業(yè)務(wù)復(fù)雜度是不會因為系統(tǒng)設(shè)計變化而減少的,它只是從一個地方轉(zhuǎn)移到了另外的地方。—— 總說自己菜的月落
讓輪子轉(zhuǎn)起來
基于讀者已經(jīng)大體理解了上節(jié)理論的基礎(chǔ)上,本節(jié)將結(jié)合上述描述的 “轉(zhuǎn)賬” 業(yè)務(wù)場景,介紹本框架的工作原理。首先讀者需要了解一下本框架的兩個名詞。
Claptrap
Claptrap 是本框架定義的一種特殊 Actor。除了上文中提到 Actor 兩種特性之外,Claptrap 還被定義為具有以下特性:
狀態(tài)由事件進行控制。Actor 的狀態(tài)在 Actor 內(nèi)部進行維護。Claptrap 同樣也是如此,不過改變 Claptrap 的狀態(tài)除了限定在 Actor 內(nèi)修改之外,還限定其只能通過事件進行改變。這就將事件溯源模式與 Actor 模式進行了結(jié)合。通過事件溯源模式保證了 Actor 狀態(tài)的正確性和可追溯性。這些改變 Claptrap 狀態(tài)的事件是由 Claptrap 自身產(chǎn)生的。事件產(chǎn)生的原因可以是外部的調(diào)用也可以是 Claptrap 內(nèi)部的類觸發(fā)器機制產(chǎn)生的。
Minion
Minion 是本框架定義的一種特殊 Actor。是在 Claptrap 基礎(chǔ)上做出的調(diào)整。其具備以下特性:
從對應(yīng)的 Claptrap 讀取事件。與 Claptrap 相同,Minion 的狀態(tài)也由事件進行控制。不同的是,Minion 就像其字面意思一樣,總是從對應(yīng)的 Claptrap 處獲取事件,從而改變自身的狀態(tài)。因此,其可以異步的處理 Claptrap 產(chǎn)生事件之后的后續(xù)操作。
業(yè)務(wù)實現(xiàn)
接下來有了前面的基礎(chǔ)介紹,現(xiàn)在介紹一下本框架如何實現(xiàn)上文中的 “轉(zhuǎn)賬” 場景。首先可以通過下圖來了解一下主要的流程:
圖片過大,原圖鏈接:https://www.newbe.pro/images/20190228-003.gif
如上圖所示,整個流程便是本框架實現(xiàn)業(yè)務(wù)場景的大體過程。另外,還有一些需要指出的是:
圖中 Client 與 Claptrap 的調(diào)用等待只有第一階段的時候存在,也就是說,這使得 Client 可以更快的得到響應(yīng),不必等待整個流程結(jié)束。
Claptrap A 在處理完自身請求,并將事件發(fā)送給 Minion A 之后就可以重新接受請求,這樣提高了 Claptrap A 的吞吐量。
Minion 不僅僅只能處理 Claptrap 之間的調(diào)用代理。在 Minion 當(dāng)中還可以根據(jù)業(yè)務(wù)需求進行:發(fā)送短信,更新數(shù)據(jù)庫統(tǒng)計數(shù)據(jù)等其他操作。
Minion 也可以具備自己的狀態(tài),將部分數(shù)據(jù)維持在自身的狀態(tài)中以便外部可以從自身進行查詢,而不需要從對應(yīng)的 Claptrap 中進行查詢。例如:統(tǒng)計該賬號最近 24 小時的轉(zhuǎn)賬變動,以便快速查詢。
業(yè)務(wù)容量
前文提到本框架需要建設(shè)的是一個可以水平擴展的系統(tǒng)架構(gòu),只有如此才能應(yīng)對業(yè)務(wù)容量的持續(xù)增長。在這點上,本框架現(xiàn)階段采用的是微軟開源的 Orleans 實現(xiàn)應(yīng)用程序和物理設(shè)備的放縮。當(dāng)然,涉及數(shù)據(jù)存儲部分時勢必也涉及到數(shù)據(jù)庫集群等一系列問題。這些屬于技術(shù)應(yīng)用的細節(jié),而非框架理論設(shè)計的內(nèi)容。因此,此處只表明本框架可以基于以上的開源架構(gòu)進行容量放縮。應(yīng)用過程中的實際問題,讀者可以在后續(xù)的項目內(nèi)容中尋求解答。
延伸閱讀
以下這些內(nèi)容都對本框架產(chǎn)生了深遠的影響。讀者可以通過閱讀以下這些內(nèi)容,增加對本框架的理解。
基于 Actor 框架 Orleans 構(gòu)建的分布式、事件溯源、事件驅(qū)動、最終一致性的高性能框架 ——Ray
Event Sourcing Pattern
Event Sourcing Pattern 中文譯文
Orleans - Distributed Virtual Actor Model
Service Fabric
ENode 1.0 - Saga 的思想與實現(xiàn)
最后但是最重要!
最近作者正在構(gòu)建以反應(yīng)式、Actor模式和事件溯源為理論基礎(chǔ)的一套服務(wù)端開發(fā)框架。希望為開發(fā)者提供能夠便于開發(fā)出 “分布式”、“可水平擴展”、“可測試性高” 的應(yīng)用系統(tǒng) ——Newbe.Claptrap
本篇文章是該框架的一篇技術(shù)選文,屬于技術(shù)構(gòu)成的一部分。如果讀者對該內(nèi)容感興趣,歡迎轉(zhuǎn)發(fā)、評論、收藏文章以及項目。您的支持是促進項目成功的關(guān)鍵。
聯(lián)系方式:
Github Issue
Gitee Issue
公開郵箱?newbe-claptrap@googlegroups.com?(發(fā)送到該郵箱的內(nèi)容將被公開)
Gitter
QQ 群 610394020
GitHub 項目地址:https://github.com/newbe36524/Newbe.Claptrap
Gitee 項目地址:https://gitee.com/yks/Newbe.Claptrap
您當(dāng)前查看的是先行發(fā)布于 www.newbe.pro 上的博客文章,實際開發(fā)文檔隨版本而迭代。若要查看最新的開發(fā)文檔,需要移步 claptrap.newbe.pro。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的Newbe.Claptrap-一套以“事件溯源”和“Actor模式”作为基本理论的服务端开发框架...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小团队前端部署演化之路
- 下一篇: NCF框架揭秘直播来了!红包、抽奖、还有