自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

醒醒吧,你根本不適合用事件驅(qū)動架構(gòu)

開發(fā) 新聞
為了防止我們的代碼變成一堆復(fù)雜的邏輯,我們應(yīng)當(dāng)在某些明確場景下使用事件驅(qū)動架構(gòu)。

一、什么是事件驅(qū)動架構(gòu)

當(dāng)下,隨著微服務(wù)的興起,容器化技術(shù)的發(fā)展,以及云原生、serverless 概念的普及,事件驅(qū)動再次引起業(yè)界的廣泛關(guān)注。

所謂事件驅(qū)動的架構(gòu),也就是使用事件來實現(xiàn)跨多個服務(wù)的業(yè)務(wù)邏輯。事件驅(qū)動架構(gòu)是一種設(shè)計應(yīng)用的軟件架構(gòu)和模型,可以最大程度減少耦合度,很好地擴(kuò)展與適配不同類型的服務(wù)組件。在這一架構(gòu)里,當(dāng)有重要事件發(fā)生時,比如更新業(yè)務(wù)數(shù)據(jù),某個服務(wù)會發(fā)布事件,其它服務(wù)則訂閱這些事件;當(dāng)某一服務(wù)接收到事件就可以執(zhí)行自己的業(yè)務(wù)流程,更新業(yè)務(wù)數(shù)據(jù),同時發(fā)布新的事件觸發(fā)下一步。

事件的發(fā)布與訂閱,需要依賴于一個可靠的消息代理。見下圖:

圖片

當(dāng)然,事實上有不少軟件項目都使用了消息隊列,但是這里需要明確的是,對消息隊列的使用并不意味著你的項目就一定是事件驅(qū)動架構(gòu),很多項目只是由于技術(shù)方面的驅(qū)動,小范圍地采用了某些消息隊列的產(chǎn)品而已。偌大一個系統(tǒng),如果你的消息隊列只是用作郵件發(fā)送的通知,那么這樣系統(tǒng)自然談不上采用了事件驅(qū)動架構(gòu)。

在采用事件驅(qū)動架構(gòu)時,我們需要考慮業(yè)務(wù)的建模、事件的設(shè)計、上下文的邊界以及更多技術(shù)方面的因素,這個系統(tǒng)工程應(yīng)該如何從頭到尾的落地,是需要經(jīng)過思考和推敲的??偠灾?,“事件驅(qū)動架構(gòu)”的設(shè)計并不是一件易事。本文在后面有個例子供參考。

另外,如果盲目使用事件驅(qū)動設(shè)計架構(gòu),就有可能要承擔(dān)中斷業(yè)務(wù)邏輯的風(fēng)險,因為這些業(yè)務(wù)邏輯具有概念上的高度內(nèi)聚,卻采用了解耦機(jī)制將它們聯(lián)系在一起。換句話說,就是將原本需要組織在一起的代碼強(qiáng)行分離,并且這樣難于定位處理流程,還有數(shù)據(jù)一致性保證等問題。為了防止我們的代碼變成一堆復(fù)雜的邏輯,我們應(yīng)當(dāng)在某些明確場景下使用事件驅(qū)動架構(gòu)。以經(jīng)驗來講,以下三 種場景可以使用事件驅(qū)動開發(fā):

  • 組件的解耦
  • 執(zhí)行異步任務(wù)
  • 跟蹤狀態(tài)的變化

二、什么時候使用事件驅(qū)動架構(gòu)

1、組件的解耦

當(dāng)服務(wù)(或組件) A 需要執(zhí)行服務(wù) B 中的業(yè)務(wù)邏輯,相比于直接調(diào)用,我們可以向事件代理(事件分發(fā)器)中發(fā)送一個事件。服務(wù) B 通過監(jiān)聽分發(fā)器中的特殊事件類型,然后當(dāng)這類事件被接收到時去執(zhí)行它。

這意味著服務(wù) A 和服務(wù) B 都依賴于事件代理和事件,而無需關(guān)注彼此實現(xiàn):即完成它們的解耦。見下圖:

圖片

基于這種松耦合,服務(wù)可以用不同的語言實現(xiàn)。解耦后的服務(wù)能夠輕松地在網(wǎng)絡(luò)上相互獨立地擴(kuò)展,通過動態(tài)添加或刪除事件生產(chǎn)者和消費者來修改他們的系統(tǒng),而不需要更改任何服務(wù)中的任何邏輯。

2、執(zhí)行異步任務(wù)

有時我們會有一系列需要執(zhí)行的業(yè)務(wù)邏輯,但是由于它們需要耗費相當(dāng)長的執(zhí)行時間,所以我們不想看到用戶耗費時間去等待這些邏輯處理完成。在這種情況下,最好將它們作為異步任務(wù)來運行,并立即向用戶返回一條信息,通知其稍后繼續(xù)處理相關(guān)操作。

比如,內(nèi)容字段的檢查等入庫流程可以采用“同步”執(zhí)行處理,但是執(zhí)行內(nèi)容理解則采用”異步“任務(wù)去處理。在這種情況下,我們所要做的是觸發(fā)一個事件,將事件加入到任務(wù)隊列中,直到一個服務(wù)能夠獲取并執(zhí)行這個任務(wù)。此時,相關(guān)的業(yè)務(wù)邏輯是否處在同一個上下文中環(huán)境中并不重要,不管怎么說,業(yè)務(wù)邏輯都是被執(zhí)行了。

3、跟蹤狀態(tài)的變化

在傳統(tǒng)的數(shù)據(jù)存儲方式中,我們通過實體模型存數(shù)據(jù)。當(dāng)這些實體模型中的數(shù)據(jù)發(fā)生變化時,我們只需更新數(shù)據(jù)庫中的行記錄來表示新的值。這里有個問題,就是業(yè)務(wù)上我們無法準(zhǔn)確存儲數(shù)據(jù)的變更和修改時間。但是在事件驅(qū)動架構(gòu)中,可以通過事件溯源將包含修改的內(nèi)容存入到事件里。下面會詳細(xì)討論“事件溯源“。

三、為什么使用事件驅(qū)動架構(gòu)

當(dāng)大家談?wù)撌录?qū)動架構(gòu)時,比如大家說自己恰好在最近的項目中采用了事件驅(qū)動架構(gòu),實際上,他們可能在談?wù)撓旅孢@四種模式中的一種或者幾種:

  • 事件承載狀態(tài)轉(zhuǎn)移
  • 事件溯源
  • CQRS

注:概念來源2017年GOTO Conference上Martin Fowler分享的The many meanings of Event-Driven architecture。

1、事件通知

假設(shè)我們現(xiàn)在想要設(shè)計一個簡易的內(nèi)容平臺,包含三部分:

  • 內(nèi)容引入系統(tǒng)
  • 作者微服務(wù)
  • 關(guān)注中心

當(dāng)內(nèi)容創(chuàng)作者通過內(nèi)容引入系統(tǒng)上傳視頻之后,會觸發(fā)如下的一個調(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)注了這個創(chuàng)作者的其他用戶發(fā)送作者視頻更新的通知。

上面這個調(diào)用流程,不可避免地創(chuàng)建了下面的依賴關(guān)系:

  • 內(nèi)容引入系統(tǒng)依賴于作者微服務(wù)的API,雖然內(nèi)容引入系統(tǒng)其實不太關(guān)心作者微服務(wù)的業(yè)務(wù)。
  • 作者微服務(wù)依賴于關(guān)注中心的API,雖然作者微服務(wù)也不關(guān)心關(guān)注中心的業(yè)務(wù)和處理流程。

這種依賴關(guān)系很有可能并不是我們所期望的。內(nèi)容引入系統(tǒng)是一個比較通用的業(yè)務(wù),不同類型的內(nèi)容引入系統(tǒng)很可能會有相似功能,如字段類型檢查、入內(nèi)容庫、啟動高敏審核等。作者服務(wù)則是一個非常專業(yè)的系統(tǒng),如不同源、不同類型的內(nèi)容關(guān)于作者的業(yè)務(wù)邏輯是不同的。讓一個通用的系統(tǒng)依賴于一個專業(yè)的系統(tǒng),不管從設(shè)計角度,還是后續(xù)系統(tǒng)維護(hù)角度,都是不一個好的方案。作者微服務(wù)可能會經(jīng)常根據(jù)業(yè)務(wù)需求做變更,但內(nèi)容引入系統(tǒng)相對穩(wěn)定,而上面這種依賴關(guān)系讓我們難以在“不對內(nèi)容引入系統(tǒng)做調(diào)整的情況”下隨意更改作者微服務(wù)。

從架構(gòu)層面,我們希望讓作者微服務(wù)依賴于內(nèi)容引入系統(tǒng),讓一個專業(yè)的系統(tǒng)依賴于一個穩(wěn)定的、通用的系統(tǒng),增加系統(tǒng)的穩(wěn)定性。這個時候我們可以借助于“事件通知”。見下圖:

圖片

1)優(yōu)點

架構(gòu)更健壯。如果加入隊列的事件能夠在源組件中執(zhí)行,但在其它組件中由于 bug 導(dǎo)致其無法執(zhí)行(由于將其加入到隊列任務(wù)中,它們可以在 bug 修復(fù)后再執(zhí)行)。

業(yè)務(wù)處理減少延遲。當(dāng)用戶無需等待所有的邏輯都執(zhí)行完成時,可以將這類工作加入到事件隊列。

便于系統(tǒng)擴(kuò)展,能夠讓組件的研發(fā)團(tuán)隊獨立開發(fā),加快項目進(jìn)度、降低功能難度、減少問題發(fā)生并且更有組織性。

將信息封裝在“事件”里,便于系統(tǒng)內(nèi)傳播。

2)缺點

如果沒有合理使用,可能使我們的代碼變成“面條式”代碼。

數(shù)據(jù)一致性問題。由于流程依賴于最終的一致性,因此通常不支持ACID事務(wù),因此重復(fù)或亂序事件的處理會使服務(wù)代碼更加復(fù)雜,并且難以測試和調(diào)試所有情況。

“事件通知”的缺點和優(yōu)點相對應(yīng),正是因為它提供了很好的解耦能力,我們會比較難通過閱讀代碼去得到整個系統(tǒng)和流程的全貌。因為這些邏輯之間的關(guān)系不再是之前的依賴關(guān)系。這將會是一個挑戰(zhàn)。

2、事件承載狀態(tài)轉(zhuǎn)移

我們在使用事件通知時,事件里面往往不會包含下游系統(tǒng)處理這個事件需要的所有信息。比如當(dāng)內(nèi)容發(fā)生下架變更時,內(nèi)容平臺會生成一個“內(nèi)容下架“的事件,但當(dāng)下游系統(tǒng)處理這個事件時,往往還需要知道,該內(nèi)容上個狀態(tài)是什么,是誰觸發(fā)下架等信息,才能完成后續(xù)處理。所以不可避免地,下游系統(tǒng)在處理這個事件時,往往還需要通過平臺服務(wù)來獲取這些額外信息。

為了解決這個問題,我們引入一個種新的模式,叫做“事件承載狀態(tài)轉(zhuǎn)移”。簡單來說,就是讓事件的消費方自己保留一份在業(yè)務(wù)處理過程中需要用到的上游系統(tǒng)的數(shù)據(jù)。比如讓下游系統(tǒng)保留一份在處理內(nèi)容狀態(tài)變更事件時所需要用到的內(nèi)容變更前的狀態(tài),避免回頭去平臺查詢。

1)優(yōu)點

架構(gòu)更健壯。減少事件消費方對生產(chǎn)方的額外依賴(獲取事件處理所需數(shù)據(jù));

業(yè)務(wù)處理減少延遲。增加事件消費方系統(tǒng)的響應(yīng)速度,因為不再需要調(diào)用平臺API以獲取事件處理所需數(shù)據(jù);

無需擔(dān)心被查詢組件的負(fù)載(尤其是遠(yuǎn)程組件)。

2)缺點

盡管現(xiàn)在數(shù)據(jù)存儲已經(jīng)不再是問題根源,依然會保存多個只讀的數(shù)據(jù)副本,一致性進(jìn)一步被破壞;

增加數(shù)據(jù)處理的復(fù)雜度,即使處理邏輯符合規(guī)范,它也需要額外處理和維護(hù)外部數(shù)據(jù)的本地副本業(yè)務(wù)邏輯。

3、事件溯源

有些時候我們不但關(guān)心系統(tǒng)當(dāng)前的狀態(tài),我們還關(guān)心如何變成當(dāng)前這個狀態(tài)的,但是數(shù)據(jù)庫僅僅簡單地保存實體的當(dāng)前狀態(tài)。事件溯源可以幫助我們解決這個問題。

事件溯源是一個特別的思路,它并不持久化實體對象,而是只把初始狀態(tài)和每次變更的事件記錄下來,并在內(nèi)存中根據(jù)事件還原實體對象的最新狀態(tài),mysql主從備份用到的binary log以及redis的aof持久化機(jī)制,都可以認(rèn)為是“事件溯源”的實現(xiàn)。

事件溯源在做完數(shù)據(jù)庫更新之后,它將事件的發(fā)送操作轉(zhuǎn)換為往數(shù)據(jù)庫或者日志系統(tǒng)中寫入一條事件記錄,其它節(jié)點通過查詢數(shù)據(jù)庫或者文件系統(tǒng),來得到這些事件,并通過回放來確保數(shù)據(jù)的最終一致性。

1)優(yōu)點

可以呈現(xiàn)一個完整的變動歷史;

提供更方便的debug手段;

可以回溯到任何一個歷史狀態(tài);

方便修改當(dāng)前事件;

2)缺點

要實現(xiàn)一個可靠和高性能的事件倉庫(保存的事件記錄)并不是一件容易的事情,應(yīng)用代碼需要根據(jù)事件庫的 API 進(jìn)行重寫。

4、CQRS

CQRS全稱是Command Query Responsibility Segregation。簡單來說,就是針對系統(tǒng)的讀寫操作,使用不同的數(shù)據(jù)模型、API接口、安全機(jī)制等,來達(dá)到對讀寫操作的完全隔離,滿足不同的業(yè)務(wù)需求。見下圖:

圖片

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

圖片

四、事件驅(qū)動架構(gòu)在內(nèi)容平臺中的實踐

在當(dāng)今社會,內(nèi)容“橫行”的時代,內(nèi)容平臺企業(yè)需要有極強(qiáng)的靈活性和應(yīng)變能力。特別是在中國這樣一個內(nèi)容行業(yè)(如視頻)飛速發(fā)展的市場里,企業(yè)要求平臺能夠快速地對內(nèi)容業(yè)務(wù)需求做出應(yīng)對,否則就會喪失先發(fā)優(yōu)勢。這有點類似于現(xiàn)代戰(zhàn)爭條件下,各國都要求部隊具備快速反應(yīng)能力,這種能力主要體現(xiàn)在平臺能夠通過快速開發(fā)或者重用 / 整合現(xiàn)有資源來達(dá)到快速響應(yīng)業(yè)務(wù)需求。

隨著內(nèi)容行業(yè)業(yè)務(wù)越來越龐大復(fù)雜,所涉及的存儲類型、處理器、賬號體系、效率工具、數(shù)據(jù)和結(jié)算系統(tǒng)等非常多,這就要求平臺有很強(qiáng)的整合能力以及對異構(gòu)環(huán)境的適配能力。

最后,由于內(nèi)容行業(yè)的發(fā)展日新月異,特定類型的內(nèi)容業(yè)務(wù)(如小視頻)都會在其初中期發(fā)展后迎來一個快速膨脹期,業(yè)務(wù)量和業(yè)務(wù)類型會急劇增加,這也要求平臺有很好的可擴(kuò)展性。相關(guān)平臺架構(gòu)見下圖:

圖片

1、創(chuàng)建事件

事件其實是DDD(領(lǐng)域驅(qū)動設(shè)計)中的一個概念,表示的是在一個領(lǐng)域中所發(fā)生的一次對業(yè)務(wù)有價值的事情,落到技術(shù)層面就是任何影響業(yè)務(wù)流程或者狀態(tài)的改變。事件具有自己的屬性,比如發(fā)生的時間、發(fā)生了什么、事件之間的關(guān)系、狀態(tài)以及變化,事件也可以生成新的事件,根據(jù)不同的事件生成新的業(yè)務(wù)事件。在創(chuàng)建事件時,首先需要記錄事件的一些通用信息,比如唯一標(biāo)識ID和創(chuàng)建時間等,為此創(chuàng)建事件基類ContentEvent:

public abstract class AbstractContentEvent {
private String eventId;
private String publisher;
private String receiver;
private Long publishTime;
}

在一般場景下,事件一般隨著聚合根(也是DDD的一個概念,這里泛指視頻id)狀態(tài)的更新而產(chǎn)生,另外,在事件的消費方,有時我們希望監(jiān)聽發(fā)生在某個聚合根下的所有事件,為此建議為每一個聚合根對象創(chuàng)建相應(yīng)的事件基類,其中包含聚合根videoId,比如對于視頻(Video)類,創(chuàng)建VideoEvent:

public class VideoEvent extends AbstractContentEvent {
private final String videoId;
}

然后對于實際的視頻事件,統(tǒng)一繼承自VideoEvent,比如對于視頻引入的VideoInputEvent事件;

public class VideoInputEvent extends VideoEvent {
private Article article; // 視頻基本信息
}

視頻域事件的繼承鏈見下圖;

圖片

在創(chuàng)建事件時,需要注意兩點:

事件本身應(yīng)該是不變的;

事件應(yīng)該攜帶與事件發(fā)生時相關(guān)的上下文數(shù)據(jù)信息,但是并不是整個聚合根的狀態(tài)數(shù)據(jù)。例如,在視頻引入時可以攜帶視頻的基本信息article,而對于視頻狀態(tài)更新的VideoStatusChangeEvent事件,則應(yīng)該同時包含更新前后的狀態(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ù)處理過程都會更新數(shù)據(jù)庫然后發(fā)布事件,這里一個比較常見的場景是:需要保證數(shù)據(jù)庫更新和事件發(fā)布之間的原子性,也即要么二者都成功,要么都失敗;當(dāng)然也有不需要保證原子性的場景。如果需要保證原子性,以“內(nèi)容引入”的業(yè)務(wù)流程為例,見下圖:

圖片

  • 接收內(nèi)容;
  • 寫入內(nèi)容表;
  • 寫入事件表,且和內(nèi)容表的更新在同一個本地數(shù)據(jù)庫事務(wù)中;
  • 事務(wù)完成后,觸發(fā)事件的發(fā)送;
  • 讀取事件表;
  • 將事件發(fā)送到消息隊列;
  • 發(fā)送成功后,將記錄標(biāo)注為“已發(fā)送”;

3、消費事件

在消費事件時,除了完成基本的消息處理邏輯外,我們需要重點關(guān)注以下三點:

  • 消費方的冪等性;
  • 消費方有可能進(jìn)一步產(chǎn)生事件;
  • 消費方的數(shù)據(jù)一致性;

對于“冪等性”,事件的發(fā)送機(jī)制保證的是“至少一次投遞”,這是有消息中間件保證,技術(shù)選型時需要注意。為了能夠正確地處理重復(fù)消息,要求消費方是冪等的,即多次消費事件與單次消費該事件的效果相同。保證“消費冪等性”的方法有很多,這里介紹一種。在消費方創(chuàng)建一個事件表,用于記錄已經(jīng)消費過的事件,在處理事件時,首先檢查該事件是否已經(jīng)被消費過,如果是則不做任何消費處理。

對于第二點,依然沿用前文講到的“事件表”的方式。事實上,無論是處理服務(wù)請求,還是作為消息的消費方,對于聚合根(videoId)來講都是無感知的,事件由聚合根產(chǎn)生進(jìn)而由事件庫持久化,這些過程都與具體的業(yè)務(wù)操作源頭無關(guān)。

對于“數(shù)據(jù)一致性”,本質(zhì)上是由第二點引出,事件驅(qū)動架構(gòu)在業(yè)務(wù)對象之間通過異步的消息來同步狀態(tài),有些消息也可以同時發(fā)布給多個服務(wù),在“消息引起了一個服務(wù)的同步”后可能會引起另外的消息,事件會擴(kuò)散開。嚴(yán)格意義上的事件驅(qū)動是沒有同步調(diào)用的,如何保證一致性,就要比非事件驅(qū)動架構(gòu)要復(fù)雜,通常采用“cache aside”模式和“分布式鎖”來保證一致性。

綜上,在消費事件的過程中,應(yīng)用程序需要更新業(yè)務(wù)表、事件記錄表,此時整個事件的發(fā)布和消費過程見下圖;

圖片

五、總結(jié)

主流場景下,傳統(tǒng)面向服務(wù)(或以數(shù)據(jù)驅(qū)動)的平臺存在系統(tǒng)性不足,需要增強(qiáng)以下能力:

  • 在傳統(tǒng)數(shù)據(jù)集成基礎(chǔ)上需要進(jìn)一步提升業(yè)務(wù)集成能力。
  • 需要提高集成平臺的業(yè)務(wù)敏捷性和反應(yīng)能力。
  • 需要進(jìn)一步實現(xiàn)業(yè)務(wù)系統(tǒng)間的解耦和高可靠性。
  • 需要進(jìn)一步提升管控平臺的實時響應(yīng)能力。

”事件驅(qū)動架構(gòu)“天然地滿足了這些能力要求。事件驅(qū)動架構(gòu)”天生“的優(yōu)點,比如,封裝、高內(nèi)聚和低耦合,還可以提升代碼的可維護(hù)性、性能和業(yè)務(wù)增長的需求,通過事件溯源模式,還能提高系統(tǒng)數(shù)據(jù)的可靠性。

不過,事件驅(qū)動同樣存在弊端,因為無論是概念上的復(fù)雜度還是技術(shù)上的復(fù)雜度都增加了,當(dāng)它被濫用時將導(dǎo)致災(zāi)難性的后果。所以,在技術(shù)棧的選用方面,給出以下寄語:

1)不要“盲目的追新” 技術(shù)人員的喜好往往是什么技術(shù)流行就追什么技術(shù)。現(xiàn)在的技術(shù)發(fā)展快,前后端不斷涌現(xiàn)各種框架,我們恨不得把這些框架都用在自己的項目里才行,按實際出發(fā),按需所用,適當(dāng)?shù)念A(yù)留技術(shù)預(yù)研的空間。

2)不要“按技術(shù)站隊,以結(jié)果反推“ 很多人把手段當(dāng)成了目的,成為了框架的信徒。用了Java開發(fā),你的設(shè)計就一定是面向?qū)ο髥幔坑昧薙pring boot就是微服務(wù)了嗎?一定要技術(shù)和實際場景結(jié)合,架構(gòu)師也要深入了解掌握技術(shù),但是更多的是了解技術(shù)的優(yōu)劣和使用場景,而不是簡單的生搬硬套。

責(zé)任編輯:張燕妮 來源: dbaplus社群
相關(guān)推薦

2015-09-18 10:01:11

2013-08-13 14:33:17

程序員

2013-08-16 10:00:45

VMwareOpenStack

2015-03-12 13:39:48

Hadoop場景大數(shù)據(jù)

2021-01-31 18:52:36

Rust開發(fā)Web API

2023-09-04 07:16:39

原子化CSS語義化CSS

2019-10-12 11:15:10

數(shù)據(jù)庫工具技術(shù)

2009-01-15 18:30:11

服務(wù)器虛擬化VMware

2018-07-29 07:58:34

物聯(lián)網(wǎng)IOT物聯(lián)網(wǎng)產(chǎn)品

2018-03-27 10:52:59

程序員不適合C++

2015-10-13 14:23:42

特質(zhì)適合創(chuàng)業(yè)

2010-07-20 09:56:53

VDI部署

2022-07-12 14:04:19

Kafka

2012-03-13 15:28:47

Kindle Fire傲游

2013-12-09 10:16:03

Android firAndroid開發(fā)移動創(chuàng)業(yè)

2022-11-07 10:20:20

useEffects

2016-11-04 09:41:48

容器Docker

2024-10-06 13:00:05

2009-01-08 17:15:29

服務(wù)器虛擬化高性能計算

2019-08-26 00:37:19

WiFi 65GWi-Fi
點贊
收藏

51CTO技術(shù)棧公眾號