醒醒吧,你根本不適合用事件驅(qū)動(dòng)架構(gòu)
一、什么是事件驅(qū)動(dòng)架構(gòu)
當(dāng)下,隨著微服務(wù)的興起,容器化技術(shù)的發(fā)展,以及云原生、serverless 概念的普及,事件驅(qū)動(dòng)再次引起業(yè)界的廣泛關(guān)注。
所謂事件驅(qū)動(dòng)的架構(gòu),也就是使用事件來實(shí)現(xiàn)跨多個(gè)服務(wù)的業(yè)務(wù)邏輯。事件驅(qū)動(dòng)架構(gòu)是一種設(shè)計(jì)應(yīng)用的軟件架構(gòu)和模型,可以最大程度減少耦合度,很好地?cái)U(kuò)展與適配不同類型的服務(wù)組件。在這一架構(gòu)里,當(dāng)有重要事件發(fā)生時(shí),比如更新業(yè)務(wù)數(shù)據(jù),某個(gè)服務(wù)會(huì)發(fā)布事件,其它服務(wù)則訂閱這些事件;當(dāng)某一服務(wù)接收到事件就可以執(zhí)行自己的業(yè)務(wù)流程,更新業(yè)務(wù)數(shù)據(jù),同時(shí)發(fā)布新的事件觸發(fā)下一步。
事件的發(fā)布與訂閱,需要依賴于一個(gè)可靠的消息代理。見下圖:

當(dāng)然,事實(shí)上有不少軟件項(xiàng)目都使用了消息隊(duì)列,但是這里需要明確的是,對(duì)消息隊(duì)列的使用并不意味著你的項(xiàng)目就一定是事件驅(qū)動(dòng)架構(gòu),很多項(xiàng)目只是由于技術(shù)方面的驅(qū)動(dòng),小范圍地采用了某些消息隊(duì)列的產(chǎn)品而已。偌大一個(gè)系統(tǒng),如果你的消息隊(duì)列只是用作郵件發(fā)送的通知,那么這樣系統(tǒng)自然談不上采用了事件驅(qū)動(dòng)架構(gòu)。
在采用事件驅(qū)動(dòng)架構(gòu)時(shí),我們需要考慮業(yè)務(wù)的建模、事件的設(shè)計(jì)、上下文的邊界以及更多技術(shù)方面的因素,這個(gè)系統(tǒng)工程應(yīng)該如何從頭到尾的落地,是需要經(jīng)過思考和推敲的。總而言之,“事件驅(qū)動(dòng)架構(gòu)”的設(shè)計(jì)并不是一件易事。本文在后面有個(gè)例子供參考。
另外,如果盲目使用事件驅(qū)動(dòng)設(shè)計(jì)架構(gòu),就有可能要承擔(dān)中斷業(yè)務(wù)邏輯的風(fēng)險(xiǎn),因?yàn)檫@些業(yè)務(wù)邏輯具有概念上的高度內(nèi)聚,卻采用了解耦機(jī)制將它們聯(lián)系在一起。換句話說,就是將原本需要組織在一起的代碼強(qiáng)行分離,并且這樣難于定位處理流程,還有數(shù)據(jù)一致性保證等問題。為了防止我們的代碼變成一堆復(fù)雜的邏輯,我們應(yīng)當(dāng)在某些明確場景下使用事件驅(qū)動(dòng)架構(gòu)。以經(jīng)驗(yàn)來講,以下三 種場景可以使用事件驅(qū)動(dòng)開發(fā):
- 組件的解耦
- 執(zhí)行異步任務(wù)
- 跟蹤狀態(tài)的變化
二、什么時(shí)候使用事件驅(qū)動(dòng)架構(gòu)
1、組件的解耦
當(dāng)服務(wù)(或組件) A 需要執(zhí)行服務(wù) B 中的業(yè)務(wù)邏輯,相比于直接調(diào)用,我們可以向事件代理(事件分發(fā)器)中發(fā)送一個(gè)事件。服務(wù) B 通過監(jiān)聽分發(fā)器中的特殊事件類型,然后當(dāng)這類事件被接收到時(shí)去執(zhí)行它。
這意味著服務(wù) A 和服務(wù) B 都依賴于事件代理和事件,而無需關(guān)注彼此實(shí)現(xiàn):即完成它們的解耦。見下圖:

基于這種松耦合,服務(wù)可以用不同的語言實(shí)現(xiàn)。解耦后的服務(wù)能夠輕松地在網(wǎng)絡(luò)上相互獨(dú)立地?cái)U(kuò)展,通過動(dòng)態(tài)添加或刪除事件生產(chǎn)者和消費(fèi)者來修改他們的系統(tǒng),而不需要更改任何服務(wù)中的任何邏輯。
2、執(zhí)行異步任務(wù)
有時(shí)我們會(huì)有一系列需要執(zhí)行的業(yè)務(wù)邏輯,但是由于它們需要耗費(fèi)相當(dāng)長的執(zhí)行時(shí)間,所以我們不想看到用戶耗費(fèi)時(shí)間去等待這些邏輯處理完成。在這種情況下,最好將它們作為異步任務(wù)來運(yùn)行,并立即向用戶返回一條信息,通知其稍后繼續(xù)處理相關(guān)操作。
比如,內(nèi)容字段的檢查等入庫流程可以采用“同步”執(zhí)行處理,但是執(zhí)行內(nèi)容理解則采用”異步“任務(wù)去處理。在這種情況下,我們所要做的是觸發(fā)一個(gè)事件,將事件加入到任務(wù)隊(duì)列中,直到一個(gè)服務(wù)能夠獲取并執(zhí)行這個(gè)任務(wù)。此時(shí),相關(guān)的業(yè)務(wù)邏輯是否處在同一個(gè)上下文中環(huán)境中并不重要,不管怎么說,業(yè)務(wù)邏輯都是被執(zhí)行了。
3、跟蹤狀態(tài)的變化
在傳統(tǒng)的數(shù)據(jù)存儲(chǔ)方式中,我們通過實(shí)體模型存數(shù)據(jù)。當(dāng)這些實(shí)體模型中的數(shù)據(jù)發(fā)生變化時(shí),我們只需更新數(shù)據(jù)庫中的行記錄來表示新的值。這里有個(gè)問題,就是業(yè)務(wù)上我們無法準(zhǔn)確存儲(chǔ)數(shù)據(jù)的變更和修改時(shí)間。但是在事件驅(qū)動(dòng)架構(gòu)中,可以通過事件溯源將包含修改的內(nèi)容存入到事件里。下面會(huì)詳細(xì)討論“事件溯源“。
三、為什么使用事件驅(qū)動(dòng)架構(gòu)
當(dāng)大家談?wù)撌录?qū)動(dòng)架構(gòu)時(shí),比如大家說自己恰好在最近的項(xiàng)目中采用了事件驅(qū)動(dòng)架構(gòu),實(shí)際上,他們可能在談?wù)撓旅孢@四種模式中的一種或者幾種:
- 事件承載狀態(tài)轉(zhuǎn)移
- 事件溯源
- CQRS
注:概念來源2017年GOTO Conference上Martin Fowler分享的The many meanings of Event-Driven architecture。
1、事件通知
假設(shè)我們現(xiàn)在想要設(shè)計(jì)一個(gè)簡易的內(nèi)容平臺(tái),包含三部分:
- 內(nèi)容引入系統(tǒng)
- 作者微服務(wù)
- 關(guān)注中心
當(dāng)內(nèi)容創(chuàng)作者通過內(nèi)容引入系統(tǒng)上傳視頻之后,會(huì)觸發(fā)如下的一個(gè)調(diào)用流程見下圖:

- 內(nèi)容引入系統(tǒng)收到創(chuàng)作者上傳的視頻,執(zhí)行入庫流程;
- 內(nèi)容引入系統(tǒng)調(diào)用作者微服務(wù)的API,增加“視頻-創(chuàng)作者”的從屬關(guān)系;
- 作者服務(wù)調(diào)用關(guān)注中心的API,讓關(guān)注中心給關(guān)注了這個(gè)創(chuàng)作者的其他用戶發(fā)送作者視頻更新的通知。
上面這個(gè)調(diào)用流程,不可避免地創(chuàng)建了下面的依賴關(guān)系:
- 內(nèi)容引入系統(tǒng)依賴于作者微服務(wù)的API,雖然內(nèi)容引入系統(tǒng)其實(shí)不太關(guān)心作者微服務(wù)的業(yè)務(wù)。
- 作者微服務(wù)依賴于關(guān)注中心的API,雖然作者微服務(wù)也不關(guān)心關(guān)注中心的業(yè)務(wù)和處理流程。
這種依賴關(guān)系很有可能并不是我們所期望的。內(nèi)容引入系統(tǒng)是一個(gè)比較通用的業(yè)務(wù),不同類型的內(nèi)容引入系統(tǒng)很可能會(huì)有相似功能,如字段類型檢查、入內(nèi)容庫、啟動(dòng)高敏審核等。作者服務(wù)則是一個(gè)非常專業(yè)的系統(tǒng),如不同源、不同類型的內(nèi)容關(guān)于作者的業(yè)務(wù)邏輯是不同的。讓一個(gè)通用的系統(tǒng)依賴于一個(gè)專業(yè)的系統(tǒng),不管從設(shè)計(jì)角度,還是后續(xù)系統(tǒng)維護(hù)角度,都是不一個(gè)好的方案。作者微服務(wù)可能會(huì)經(jīng)常根據(jù)業(yè)務(wù)需求做變更,但內(nèi)容引入系統(tǒng)相對(duì)穩(wěn)定,而上面這種依賴關(guān)系讓我們難以在“不對(duì)內(nèi)容引入系統(tǒng)做調(diào)整的情況”下隨意更改作者微服務(wù)。
從架構(gòu)層面,我們希望讓作者微服務(wù)依賴于內(nèi)容引入系統(tǒng),讓一個(gè)專業(yè)的系統(tǒng)依賴于一個(gè)穩(wěn)定的、通用的系統(tǒng),增加系統(tǒng)的穩(wěn)定性。這個(gè)時(shí)候我們可以借助于“事件通知”。見下圖:

1)優(yōu)點(diǎn)
架構(gòu)更健壯。如果加入隊(duì)列的事件能夠在源組件中執(zhí)行,但在其它組件中由于 bug 導(dǎo)致其無法執(zhí)行(由于將其加入到隊(duì)列任務(wù)中,它們可以在 bug 修復(fù)后再執(zhí)行)。
業(yè)務(wù)處理減少延遲。當(dāng)用戶無需等待所有的邏輯都執(zhí)行完成時(shí),可以將這類工作加入到事件隊(duì)列。
便于系統(tǒng)擴(kuò)展,能夠讓組件的研發(fā)團(tuán)隊(duì)獨(dú)立開發(fā),加快項(xiàng)目進(jìn)度、降低功能難度、減少問題發(fā)生并且更有組織性。
將信息封裝在“事件”里,便于系統(tǒng)內(nèi)傳播。
2)缺點(diǎn)
如果沒有合理使用,可能使我們的代碼變成“面條式”代碼。
數(shù)據(jù)一致性問題。由于流程依賴于最終的一致性,因此通常不支持ACID事務(wù),因此重復(fù)或亂序事件的處理會(huì)使服務(wù)代碼更加復(fù)雜,并且難以測試和調(diào)試所有情況。
“事件通知”的缺點(diǎn)和優(yōu)點(diǎn)相對(duì)應(yīng),正是因?yàn)樗峁┝撕芎玫慕怦钅芰Γ覀儠?huì)比較難通過閱讀代碼去得到整個(gè)系統(tǒng)和流程的全貌。因?yàn)檫@些邏輯之間的關(guān)系不再是之前的依賴關(guān)系。這將會(huì)是一個(gè)挑戰(zhàn)。
2、事件承載狀態(tài)轉(zhuǎn)移
我們在使用事件通知時(shí),事件里面往往不會(huì)包含下游系統(tǒng)處理這個(gè)事件需要的所有信息。比如當(dāng)內(nèi)容發(fā)生下架變更時(shí),內(nèi)容平臺(tái)會(huì)生成一個(gè)“內(nèi)容下架“的事件,但當(dāng)下游系統(tǒng)處理這個(gè)事件時(shí),往往還需要知道,該內(nèi)容上個(gè)狀態(tài)是什么,是誰觸發(fā)下架等信息,才能完成后續(xù)處理。所以不可避免地,下游系統(tǒng)在處理這個(gè)事件時(shí),往往還需要通過平臺(tái)服務(wù)來獲取這些額外信息。
為了解決這個(gè)問題,我們引入一個(gè)種新的模式,叫做“事件承載狀態(tài)轉(zhuǎn)移”。簡單來說,就是讓事件的消費(fèi)方自己保留一份在業(yè)務(wù)處理過程中需要用到的上游系統(tǒng)的數(shù)據(jù)。比如讓下游系統(tǒng)保留一份在處理內(nèi)容狀態(tài)變更事件時(shí)所需要用到的內(nèi)容變更前的狀態(tài),避免回頭去平臺(tái)查詢。
1)優(yōu)點(diǎn)
架構(gòu)更健壯。減少事件消費(fèi)方對(duì)生產(chǎn)方的額外依賴(獲取事件處理所需數(shù)據(jù));
業(yè)務(wù)處理減少延遲。增加事件消費(fèi)方系統(tǒng)的響應(yīng)速度,因?yàn)椴辉傩枰{(diào)用平臺(tái)API以獲取事件處理所需數(shù)據(jù);
無需擔(dān)心被查詢組件的負(fù)載(尤其是遠(yuǎn)程組件)。
2)缺點(diǎn)
盡管現(xiàn)在數(shù)據(jù)存儲(chǔ)已經(jīng)不再是問題根源,依然會(huì)保存多個(gè)只讀的數(shù)據(jù)副本,一致性進(jìn)一步被破壞;
增加數(shù)據(jù)處理的復(fù)雜度,即使處理邏輯符合規(guī)范,它也需要額外處理和維護(hù)外部數(shù)據(jù)的本地副本業(yè)務(wù)邏輯。
3、事件溯源
有些時(shí)候我們不但關(guān)心系統(tǒng)當(dāng)前的狀態(tài),我們還關(guān)心如何變成當(dāng)前這個(gè)狀態(tài)的,但是數(shù)據(jù)庫僅僅簡單地保存實(shí)體的當(dāng)前狀態(tài)。事件溯源可以幫助我們解決這個(gè)問題。
事件溯源是一個(gè)特別的思路,它并不持久化實(shí)體對(duì)象,而是只把初始狀態(tài)和每次變更的事件記錄下來,并在內(nèi)存中根據(jù)事件還原實(shí)體對(duì)象的最新狀態(tài),mysql主從備份用到的binary log以及redis的aof持久化機(jī)制,都可以認(rèn)為是“事件溯源”的實(shí)現(xiàn)。
事件溯源在做完數(shù)據(jù)庫更新之后,它將事件的發(fā)送操作轉(zhuǎn)換為往數(shù)據(jù)庫或者日志系統(tǒng)中寫入一條事件記錄,其它節(jié)點(diǎn)通過查詢數(shù)據(jù)庫或者文件系統(tǒng),來得到這些事件,并通過回放來確保數(shù)據(jù)的最終一致性。
1)優(yōu)點(diǎn)
可以呈現(xiàn)一個(gè)完整的變動(dòng)歷史;
提供更方便的debug手段;
可以回溯到任何一個(gè)歷史狀態(tài);
方便修改當(dāng)前事件;
2)缺點(diǎn)
要實(shí)現(xiàn)一個(gè)可靠和高性能的事件倉庫(保存的事件記錄)并不是一件容易的事情,應(yīng)用代碼需要根據(jù)事件庫的 API 進(jìn)行重寫。
4、CQRS
CQRS全稱是Command Query Responsibility Segregation。簡單來說,就是針對(duì)系統(tǒng)的讀寫操作,使用不同的數(shù)據(jù)模型、API接口、安全機(jī)制等,來達(dá)到對(duì)讀寫操作的完全隔離,滿足不同的業(yè)務(wù)需求。見下圖:

根據(jù)存儲(chǔ)在事件庫中的事件集合,可以計(jì)算得到每個(gè)業(yè)務(wù)實(shí)體的狀態(tài),這些狀態(tài)以物化視圖的方式存儲(chǔ)在一個(gè)數(shù)據(jù)庫中。當(dāng)有新的事件產(chǎn)生時(shí),也同樣會(huì)自動(dòng)更新視圖。這樣,視圖查詢服務(wù)就可以像查詢普通的數(shù)據(jù)庫數(shù)據(jù)一樣實(shí)現(xiàn)各種查詢場景。具體的設(shè)計(jì)可參考下圖所示:

四、事件驅(qū)動(dòng)架構(gòu)在內(nèi)容平臺(tái)中的實(shí)踐
在當(dāng)今社會(huì),內(nèi)容“橫行”的時(shí)代,內(nèi)容平臺(tái)企業(yè)需要有極強(qiáng)的靈活性和應(yīng)變能力。特別是在中國這樣一個(gè)內(nèi)容行業(yè)(如視頻)飛速發(fā)展的市場里,企業(yè)要求平臺(tái)能夠快速地對(duì)內(nèi)容業(yè)務(wù)需求做出應(yīng)對(duì),否則就會(huì)喪失先發(fā)優(yōu)勢。這有點(diǎn)類似于現(xiàn)代戰(zhàn)爭條件下,各國都要求部隊(duì)具備快速反應(yīng)能力,這種能力主要體現(xiàn)在平臺(tái)能夠通過快速開發(fā)或者重用 / 整合現(xiàn)有資源來達(dá)到快速響應(yīng)業(yè)務(wù)需求。
隨著內(nèi)容行業(yè)業(yè)務(wù)越來越龐大復(fù)雜,所涉及的存儲(chǔ)類型、處理器、賬號(hào)體系、效率工具、數(shù)據(jù)和結(jié)算系統(tǒng)等非常多,這就要求平臺(tái)有很強(qiáng)的整合能力以及對(duì)異構(gòu)環(huán)境的適配能力。
最后,由于內(nèi)容行業(yè)的發(fā)展日新月異,特定類型的內(nèi)容業(yè)務(wù)(如小視頻)都會(huì)在其初中期發(fā)展后迎來一個(gè)快速膨脹期,業(yè)務(wù)量和業(yè)務(wù)類型會(huì)急劇增加,這也要求平臺(tái)有很好的可擴(kuò)展性。相關(guān)平臺(tái)架構(gòu)見下圖:

1、創(chuàng)建事件
事件其實(shí)是DDD(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))中的一個(gè)概念,表示的是在一個(gè)領(lǐng)域中所發(fā)生的一次對(duì)業(yè)務(wù)有價(jià)值的事情,落到技術(shù)層面就是任何影響業(yè)務(wù)流程或者狀態(tài)的改變。事件具有自己的屬性,比如發(fā)生的時(shí)間、發(fā)生了什么、事件之間的關(guān)系、狀態(tài)以及變化,事件也可以生成新的事件,根據(jù)不同的事件生成新的業(yè)務(wù)事件。在創(chuàng)建事件時(shí),首先需要記錄事件的一些通用信息,比如唯一標(biāo)識(shí)ID和創(chuàng)建時(shí)間等,為此創(chuàng)建事件基類ContentEvent:
public abstract class AbstractContentEvent {
private String eventId;
private String publisher;
private String receiver;
private Long publishTime;
}
在一般場景下,事件一般隨著聚合根(也是DDD的一個(gè)概念,這里泛指視頻id)狀態(tài)的更新而產(chǎn)生,另外,在事件的消費(fèi)方,有時(shí)我們希望監(jiān)聽發(fā)生在某個(gè)聚合根下的所有事件,為此建議為每一個(gè)聚合根對(duì)象創(chuàng)建相應(yīng)的事件基類,其中包含聚合根videoId,比如對(duì)于視頻(Video)類,創(chuàng)建VideoEvent:
public class VideoEvent extends AbstractContentEvent {
private final String videoId;
}
然后對(duì)于實(shí)際的視頻事件,統(tǒng)一繼承自VideoEvent,比如對(duì)于視頻引入的VideoInputEvent事件;
public class VideoInputEvent extends VideoEvent {
private Article article; // 視頻基本信息
}
視頻域事件的繼承鏈見下圖;

在創(chuàng)建事件時(shí),需要注意兩點(diǎn):
事件本身應(yīng)該是不變的;
事件應(yīng)該攜帶與事件發(fā)生時(shí)相關(guān)的上下文數(shù)據(jù)信息,但是并不是整個(gè)聚合根的狀態(tài)數(shù)據(jù)。例如,在視頻引入時(shí)可以攜帶視頻的基本信息article,而對(duì)于視頻狀態(tài)更新的VideoStatusChangeEvent事件,則應(yīng)該同時(shí)包含更新前后的狀態(tài)status:
public class VideoStatusChangeEvent extends VideoEvent {
private String preStatus; //更新前的狀態(tài)
private String status; // 更新后的狀態(tài)
}
2、發(fā)布事件
發(fā)布事件有多種方式,比如可以在應(yīng)用程序中發(fā)布。通常的業(yè)務(wù)處理過程都會(huì)更新數(shù)據(jù)庫然后發(fā)布事件,這里一個(gè)比較常見的場景是:需要保證數(shù)據(jù)庫更新和事件發(fā)布之間的原子性,也即要么二者都成功,要么都失敗;當(dāng)然也有不需要保證原子性的場景。如果需要保證原子性,以“內(nèi)容引入”的業(yè)務(wù)流程為例,見下圖:

- 接收內(nèi)容;
- 寫入內(nèi)容表;
- 寫入事件表,且和內(nèi)容表的更新在同一個(gè)本地?cái)?shù)據(jù)庫事務(wù)中;
- 事務(wù)完成后,觸發(fā)事件的發(fā)送;
- 讀取事件表;
- 將事件發(fā)送到消息隊(duì)列;
- 發(fā)送成功后,將記錄標(biāo)注為“已發(fā)送”;
3、消費(fèi)事件
在消費(fèi)事件時(shí),除了完成基本的消息處理邏輯外,我們需要重點(diǎn)關(guān)注以下三點(diǎn):
- 消費(fèi)方的冪等性;
- 消費(fèi)方有可能進(jìn)一步產(chǎn)生事件;
- 消費(fèi)方的數(shù)據(jù)一致性;
對(duì)于“冪等性”,事件的發(fā)送機(jī)制保證的是“至少一次投遞”,這是有消息中間件保證,技術(shù)選型時(shí)需要注意。為了能夠正確地處理重復(fù)消息,要求消費(fèi)方是冪等的,即多次消費(fèi)事件與單次消費(fèi)該事件的效果相同。保證“消費(fèi)冪等性”的方法有很多,這里介紹一種。在消費(fèi)方創(chuàng)建一個(gè)事件表,用于記錄已經(jīng)消費(fèi)過的事件,在處理事件時(shí),首先檢查該事件是否已經(jīng)被消費(fèi)過,如果是則不做任何消費(fèi)處理。
對(duì)于第二點(diǎn),依然沿用前文講到的“事件表”的方式。事實(shí)上,無論是處理服務(wù)請(qǐng)求,還是作為消息的消費(fèi)方,對(duì)于聚合根(videoId)來講都是無感知的,事件由聚合根產(chǎn)生進(jìn)而由事件庫持久化,這些過程都與具體的業(yè)務(wù)操作源頭無關(guān)。
對(duì)于“數(shù)據(jù)一致性”,本質(zhì)上是由第二點(diǎn)引出,事件驅(qū)動(dòng)架構(gòu)在業(yè)務(wù)對(duì)象之間通過異步的消息來同步狀態(tài),有些消息也可以同時(shí)發(fā)布給多個(gè)服務(wù),在“消息引起了一個(gè)服務(wù)的同步”后可能會(huì)引起另外的消息,事件會(huì)擴(kuò)散開。嚴(yán)格意義上的事件驅(qū)動(dòng)是沒有同步調(diào)用的,如何保證一致性,就要比非事件驅(qū)動(dòng)架構(gòu)要復(fù)雜,通常采用“cache aside”模式和“分布式鎖”來保證一致性。
綜上,在消費(fèi)事件的過程中,應(yīng)用程序需要更新業(yè)務(wù)表、事件記錄表,此時(shí)整個(gè)事件的發(fā)布和消費(fèi)過程見下圖;

五、總結(jié)
主流場景下,傳統(tǒng)面向服務(wù)(或以數(shù)據(jù)驅(qū)動(dòng))的平臺(tái)存在系統(tǒng)性不足,需要增強(qiáng)以下能力:
- 在傳統(tǒng)數(shù)據(jù)集成基礎(chǔ)上需要進(jìn)一步提升業(yè)務(wù)集成能力。
- 需要提高集成平臺(tái)的業(yè)務(wù)敏捷性和反應(yīng)能力。
- 需要進(jìn)一步實(shí)現(xiàn)業(yè)務(wù)系統(tǒng)間的解耦和高可靠性。
- 需要進(jìn)一步提升管控平臺(tái)的實(shí)時(shí)響應(yīng)能力。
”事件驅(qū)動(dòng)架構(gòu)“天然地滿足了這些能力要求。事件驅(qū)動(dòng)架構(gòu)”天生“的優(yōu)點(diǎn),比如,封裝、高內(nèi)聚和低耦合,還可以提升代碼的可維護(hù)性、性能和業(yè)務(wù)增長的需求,通過事件溯源模式,還能提高系統(tǒng)數(shù)據(jù)的可靠性。
不過,事件驅(qū)動(dòng)同樣存在弊端,因?yàn)闊o論是概念上的復(fù)雜度還是技術(shù)上的復(fù)雜度都增加了,當(dāng)它被濫用時(shí)將導(dǎo)致災(zāi)難性的后果。所以,在技術(shù)棧的選用方面,給出以下寄語:
1)不要“盲目的追新” 技術(shù)人員的喜好往往是什么技術(shù)流行就追什么技術(shù)。現(xiàn)在的技術(shù)發(fā)展快,前后端不斷涌現(xiàn)各種框架,我們恨不得把這些框架都用在自己的項(xiàng)目里才行,按實(shí)際出發(fā),按需所用,適當(dāng)?shù)念A(yù)留技術(shù)預(yù)研的空間。
2)不要“按技術(shù)站隊(duì),以結(jié)果反推“ 很多人把手段當(dāng)成了目的,成為了框架的信徒。用了Java開發(fā),你的設(shè)計(jì)就一定是面向?qū)ο髥幔坑昧薙pring boot就是微服務(wù)了嗎?一定要技術(shù)和實(shí)際場景結(jié)合,架構(gòu)師也要深入了解掌握技術(shù),但是更多的是了解技術(shù)的優(yōu)劣和使用場景,而不是簡單的生搬硬套。

























