亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

作者 | Natan Silnitsky

譯者 | 平川

策劃 | 萬(wàn)佳

在過(guò)去一年里,我一直是數(shù)據(jù)流團(tuán)隊(duì)的一員,負(fù)責(zé) Wix 事件驅(qū)動(dòng)的消息傳遞基礎(chǔ)設(shè)施(基于 Kafka)。有超過(guò) 1400 個(gè)微服務(wù)使用這個(gè)基礎(chǔ)設(shè)施。在此期間,我實(shí)現(xiàn)或目睹了事件驅(qū)動(dòng)消息傳遞設(shè)計(jì)的幾個(gè)關(guān)鍵模式,這些模式有助于創(chuàng)建一個(gè)健壯的分布式系統(tǒng),該系統(tǒng)可以輕松地處理不斷增長(zhǎng)的流量和存儲(chǔ)需求。

1消費(fèi)與投影

針對(duì)那些使用非常廣泛、已經(jīng)成為瓶頸的服務(wù)

當(dāng)有遺留服務(wù)存儲(chǔ)著大型域?qū)ο蟮臄?shù)據(jù),這些數(shù)據(jù)使用又非常廣泛,使得該遺留服務(wù)成為瓶頸時(shí),此模式可以提供幫助。

在 Wix,我們的 MetaSite 服務(wù)就面臨著這樣的情況,它為 Wix 用戶創(chuàng)建的每個(gè)站點(diǎn)保存了大量的元數(shù)據(jù),比如站點(diǎn)版本、站點(diǎn)所有者以及站點(diǎn)上安裝了哪些應(yīng)用程序——已安裝應(yīng)用上下文(The Installed Apps Context.)。

這些信息對(duì)于 Wix 的許多其他微服務(wù)(團(tuán)隊(duì))很有價(jià)值,比如 Wix Stores、Wix booking、Wix Restaurants 等等。這個(gè)服務(wù)被超過(guò) 100 萬(wàn) RPM 的請(qǐng)求轟炸,它們需要獲取站點(diǎn)元數(shù)據(jù)的不同部分。

從服務(wù)的各種 API 可以明顯看出,它處理了客戶端服務(wù)的太多不同的關(guān)注點(diǎn)。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

MetaSite 服務(wù)處理大約 1M RPM 的各類請(qǐng)求

我們想要回答的問(wèn)題是,如何以最終一致的方式將讀請(qǐng)求從該服務(wù)轉(zhuǎn)移出來(lái)?

使用 Kafka 創(chuàng)建“物化視圖”

負(fù)責(zé)這項(xiàng)服務(wù)的團(tuán)隊(duì)決定另外創(chuàng)建一個(gè)服務(wù),只處理 MetaSite 的一個(gè)關(guān)注點(diǎn)——來(lái)自客戶端服務(wù)的“已安裝應(yīng)用上下文”請(qǐng)求。

  • 首先,他們將所有數(shù)據(jù)庫(kù)的站點(diǎn)元數(shù)據(jù)對(duì)象以流的方式傳輸?shù)?Kafka 主題中,包括新站點(diǎn)創(chuàng)建和站點(diǎn)更新。一致性可以通過(guò)在 Kafka Consumer 中進(jìn)行 DB 插入來(lái)實(shí)現(xiàn),或者通過(guò)使用 CDC 產(chǎn)品(如 Debezium)來(lái)實(shí)現(xiàn)。
  • 其次,他們創(chuàng)建了一個(gè)有自己數(shù)據(jù)庫(kù)的“只寫”服務(wù)(反向查找寫入器),該服務(wù)使用站點(diǎn)元數(shù)據(jù)對(duì)象,但只獲取已安裝應(yīng)用上下文并寫入數(shù)據(jù)庫(kù)。即將站點(diǎn)元數(shù)據(jù)的某個(gè)“視圖”(已安裝的應(yīng)用程序)投影到數(shù)據(jù)庫(kù)中。

 

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

已安裝應(yīng)用上下文消費(fèi)與投影

  • 第三,他們創(chuàng)建了一個(gè)“只讀”服務(wù),只接受與已安裝應(yīng)用上下文相關(guān)的請(qǐng)求,通過(guò)查詢存儲(chǔ)著“已安裝應(yīng)用程序”視圖的數(shù)據(jù)庫(kù)來(lái)滿足請(qǐng)求。

 

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

讀寫分離

效果

  • 通過(guò)將數(shù)據(jù)以流的方式傳輸?shù)?Kafka,MetaSite 服務(wù)完全同數(shù)據(jù)消費(fèi)者解耦,這大大降低了服務(wù)和 DB 的負(fù)載。
  • 通過(guò)消費(fèi)來(lái)自 Kafka 的數(shù)據(jù),并為特定的上下文創(chuàng)建一個(gè)“物化視圖”,反向查找寫入器服務(wù)能夠創(chuàng)建一個(gè)最終一致的數(shù)據(jù)投影,大幅優(yōu)化了客戶端服務(wù)的查詢需求。
  • 將讀服務(wù)與寫服務(wù)分開(kāi),可以方便地?cái)U(kuò)展只讀 DB 副本和服務(wù)實(shí)例的數(shù)量,這些實(shí)例可以處理來(lái)自全球多個(gè)數(shù)據(jù)中心的不斷增長(zhǎng)的查詢負(fù)載。

2端到端事件驅(qū)動(dòng)

針對(duì)簡(jiǎn)單業(yè)務(wù)流程的狀態(tài)更新

請(qǐng)求 - 應(yīng)答模型在瀏覽器 - 服務(wù)器交互中特別常見(jiàn)。借助 Kafka 和 WebSocket,我們就有了一個(gè)完整的事件流驅(qū)動(dòng),包括瀏覽器 - 服務(wù)器交互。

這使得交互過(guò)程容錯(cuò)性更好,因?yàn)橄⒃?Kafka 中被持久化,并且可以在服務(wù)重啟時(shí)重新處理。該架構(gòu)還具有更高的可伸縮性和解耦性,因?yàn)闋顟B(tài)管理完全從服務(wù)中移除,并且不需要對(duì)查詢進(jìn)行數(shù)據(jù)聚合和維護(hù)。

考慮一下這種情況,將所有 Wix 用戶的聯(lián)系方式導(dǎo)入 Wix 平臺(tái)。

這個(gè)過(guò)程涉及到兩個(gè)服務(wù):Contacts Jobs 服務(wù)處理導(dǎo)入請(qǐng)求并創(chuàng)建導(dǎo)入批處理作業(yè),Contacts Importer 執(zhí)行實(shí)際的格式化并存儲(chǔ)聯(lián)系人(有時(shí)借助第三方服務(wù))。

傳統(tǒng)的請(qǐng)求 - 應(yīng)答方法需要瀏覽器不斷輪詢導(dǎo)入狀態(tài),前端服務(wù)需要將狀態(tài)更新情況保存到數(shù)據(jù)庫(kù)表中,并輪詢下游服務(wù)以獲得狀態(tài)更新。

而使用 Kafka 和 WebSocket 管理者服務(wù),我們可以實(shí)現(xiàn)一個(gè)完全分布式的事件驅(qū)動(dòng)過(guò)程,其中每個(gè)服務(wù)都是完全獨(dú)立工作的。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

使用 Kafka 和 WebSocket 的 E2E 事件驅(qū)動(dòng)

首先,瀏覽器會(huì)根據(jù)開(kāi)始導(dǎo)入請(qǐng)求訂閱 WebSocket 服務(wù)。

它需要提供一個(gè) channel-Id,以便 WebSocket 服務(wù)能夠?qū)⑼ㄖ酚苫卣_的瀏覽器:

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

打開(kāi) WebSocket 通知“通道”

第二,瀏覽器需要向 Jobs 服務(wù)發(fā)送一個(gè) HTTP 請(qǐng)求,聯(lián)系人信息使用 CSV 格式,并附加 channel-Id,這樣 Jobs 服務(wù)(和下游服務(wù))就能夠向 WebSocket 服務(wù)發(fā)送通知。注意,HTTP 響應(yīng)將立即返回,沒(méi)有任何內(nèi)容。

第三,Jobs 服務(wù)在處理完請(qǐng)求后,會(huì)生成并向 Kafka 主題發(fā)送作業(yè)請(qǐng)求。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

HTTP Import 請(qǐng)求和生成的 Import Job 消息

第四,Contacts Importer** 服務(wù)消費(fèi)來(lái)自 Kafka 的作業(yè)請(qǐng)求,并執(zhí)行實(shí)際的導(dǎo)入任務(wù)。當(dāng)它完成時(shí),它可以通知 WebSocket 服務(wù)作業(yè)已經(jīng)完成,而 WebSocket 服務(wù)又通知瀏覽器。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

工作已消費(fèi)、已處理和已完成狀態(tài)通知

效果

  • 使用這種設(shè)計(jì),在導(dǎo)入過(guò)程的各個(gè)階段通知瀏覽器變得很簡(jiǎn)單,而且不需要保持任何狀態(tài),也不需要任何輪詢。
  • Kafka 的使用使得導(dǎo)入過(guò)程更具彈性和可擴(kuò)展性,因?yàn)槎鄠€(gè)服務(wù)可以處理來(lái)自同一個(gè)原始導(dǎo)入 http 請(qǐng)求的作業(yè)。
  • 使用 Kafka 復(fù)制,很容易將每個(gè)階段放在最合適的數(shù)據(jù)中心和地理位置。也許導(dǎo)入器服務(wù)需要在谷歌 DC 上,以便可以更快地導(dǎo)入谷歌聯(lián)系人。
  • WebSocket 服務(wù)的傳入通知請(qǐng)求也可以生成到 Kafka,然后復(fù)制到 WebSocket 服務(wù)所在的數(shù)據(jù)中心。

3內(nèi)存 KV 存儲(chǔ)

針對(duì) 0 延遲數(shù)據(jù)訪問(wèn)

有時(shí),我們需要?jiǎng)討B(tài)對(duì)應(yīng)用程序進(jìn)行持久化配置,但我們不想為它創(chuàng)建一個(gè)全面的關(guān)系數(shù)據(jù)庫(kù)表。

一個(gè)選擇是用 HBase/Cassandra/DynamoDB 為所有應(yīng)用創(chuàng)建一個(gè)大的寬列存儲(chǔ)表,其主鍵包含標(biāo)識(shí)應(yīng)用域的前綴(例如“store_taxes_”)。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

這個(gè)解決方案效果很好,但是通過(guò)網(wǎng)絡(luò)取值存在無(wú)法避免的延遲。它更適合于更大的數(shù)據(jù)集,而不僅僅是配置數(shù)據(jù)。

另一種方法是有一個(gè)位于內(nèi)存但同樣具有持久性的鍵 / 值緩存——redis AOF 提供了這種能力。

Kafka 以壓縮主題的形式為鍵 / 值存儲(chǔ)提供了類似的解決方案(保留模型確保鍵的最新值不會(huì)被刪除)。

在 Wix,我們將這些壓縮主題用作內(nèi)存中的 kv-store,我們?cè)趹?yīng)用程序啟動(dòng)時(shí)加載(消費(fèi))來(lái)自主題的數(shù)據(jù)。這有一個(gè) Redis 沒(méi)有提供的好處,這個(gè)主題還可以被其他想要獲得更新的用戶使用。

訂閱和查詢

考慮以下用例——兩個(gè)微服務(wù)使用壓縮主題來(lái)做數(shù)據(jù)維護(hù):Wix Business Manager(幫助 Wix 網(wǎng)站所有者管理他們的業(yè)務(wù))使用一個(gè)壓縮主題存放支持的國(guó)家列表,Wix Bookings(允許安排預(yù)約和課程)維護(hù)了一個(gè)“(Time Zones)”壓縮主題。從這些內(nèi)存 KV 存儲(chǔ)中檢索值的延遲為 0。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

各內(nèi)存 KV 存儲(chǔ)以及相應(yīng)的 Kafka 壓縮主題

Wix Bookings 監(jiān)聽(tīng)“國(guó)家(Countries)”主題的更新:

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

Bookings 消費(fèi)來(lái)自壓縮主題 Countries 的更新

當(dāng) Wix Business Manager 將另一個(gè)國(guó)家添加到“國(guó)家”主題時(shí),Wix Bookings 會(huì)消費(fèi)此更新,并自動(dòng)為“時(shí)區(qū)”主題添加一個(gè)新的時(shí)區(qū)。現(xiàn)在,內(nèi)存 KV 存儲(chǔ)中的“時(shí)區(qū)”也通過(guò)更新增加了新的時(shí)區(qū):

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

South Sudan 的時(shí)區(qū)被加入壓縮主題

我們沒(méi)有在這里停下來(lái)。Wix Events(供 Wix Users 管理事件傳票和 RSVP)也可以使用 Bookings 的時(shí)區(qū)主題,并在一個(gè)國(guó)家因?yàn)橄牧顣r(shí)更改時(shí)區(qū)時(shí)自動(dòng)更新其內(nèi)存 kv-store。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

兩個(gè)內(nèi)存 KV 存儲(chǔ)消費(fèi)同一個(gè)壓縮主題

4調(diào)度并遺忘

當(dāng)存在需要確保計(jì)劃事件最終被處理的需求時(shí)

在許多情況下,需要 Wix 微服務(wù)根據(jù)某個(gè)計(jì)劃執(zhí)行作業(yè)。

Wix Payments Subscriptions 服務(wù)就是一個(gè)例子,它管理基于訂閱的支付(例如瑜伽課程的訂閱)。

對(duì)于每個(gè)月度或年度訂閱用戶,必須通過(guò)支付提供程序完成續(xù)訂過(guò)程。

為此,Wix 自定義的 Job Scheduler 服務(wù)調(diào)用由 Payments Subscription 服務(wù)預(yù)先配置好的 REST 端點(diǎn)。

訂閱續(xù)期過(guò)程在后臺(tái)進(jìn)行,不需要(人類)用戶參與。這就是為什么最終可以成功續(xù)訂很重要,即使臨時(shí)有錯(cuò)誤——例如第三支付提供程序不可用。

要確保這一過(guò)程是完全彈性的,一種方法是由作業(yè)調(diào)度器重復(fù)請(qǐng)求 Payment Subscriptions 服務(wù)(續(xù)訂的當(dāng)前狀態(tài)保存在數(shù)據(jù)庫(kù)中),對(duì)每個(gè)到期但尚未續(xù)期的訂閱進(jìn)行輪詢。這將需要數(shù)據(jù)庫(kù)上的悲觀 / 樂(lè)觀鎖定,因?yàn)橥挥脩敉粫r(shí)間可能有多個(gè)訂閱續(xù)期請(qǐng)求(來(lái)自兩個(gè)單獨(dú)的正在進(jìn)行的請(qǐng)求)。

更好的方法是首先生成 Kafka 請(qǐng)求。為什么?因?yàn)檎?qǐng)求的處理將由 Kafka 的消費(fèi)者順序完成(對(duì)于每個(gè)特定的用戶),所以不需要并行工作的同步機(jī)制。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

此外,一旦消息生成并發(fā)送到 Kafka,我們就可以通過(guò)引入消費(fèi)者重試來(lái)確保它最終會(huì)被成功處理。由于有這些重試,請(qǐng)求調(diào)度的頻率可能就會(huì)低很多。

在這種情況下,我們希望可以保持處理順序,這樣重試邏輯可以在兩次嘗試之間(以“指數(shù)退避”間隔進(jìn)行)簡(jiǎn)單地休眠。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

Wix 開(kāi)發(fā)人員使用我們自定義的 Greyhound 消費(fèi)者,因此,他們只需指定一個(gè) BlockingPolicy,并根據(jù)需要指定適當(dāng)?shù)闹卦囬g隔。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

在某些情況下,消費(fèi)者和生產(chǎn)者之間可能會(huì)產(chǎn)生延遲,如長(zhǎng)時(shí)間持續(xù)出錯(cuò)。在這些情況下,有一個(gè)特殊的儀表板用于解除阻塞,并跳過(guò)開(kāi)發(fā)人員可以使用的消息。

如果消息處理順序不是強(qiáng)制性的,那么 Greyhound 中還有一個(gè)使用“重試主題”的非阻塞重試策略。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

當(dāng)配置重試策略時(shí),Greyhound 消費(fèi)者將創(chuàng)建與用戶定義的重試間隔一樣多的重試主題。內(nèi)置的重試生成器將在出錯(cuò)時(shí)生成一條下一個(gè)重試主題的消息,該消息帶有一個(gè)自定義頭,指定在下一次調(diào)用處理程序代碼之前應(yīng)該延遲多少時(shí)間。

還有一個(gè)死信隊(duì)列,用于重試次數(shù)耗盡的情況。在這種情況下,消息被放在死信隊(duì)列中,由開(kāi)發(fā)人員手動(dòng)審查。

這種重試機(jī)制是受 Uber 這篇文章的啟發(fā)。

https://eng.uber.com/reliable-reprocessing/

Wix 最近開(kāi)放了 Greyhound 的源代碼,不久將提供給測(cè)試用戶。要了解更多信息,可以閱讀 GitHub 上的自述文件。

https://github.com/wix/greyhound#greyhound

總結(jié):

  • Kafka 允許按順序處理每個(gè)鍵的請(qǐng)求(例如使用 userId 進(jìn)行續(xù)訂),簡(jiǎn)化工作進(jìn)程邏輯;
  • 由于 Kafka 重試策略的實(shí)現(xiàn)大大提高了容錯(cuò)能力,續(xù)期請(qǐng)求的作業(yè)調(diào)度頻率大大降低。

5事務(wù)中的事件

當(dāng)冪等性很難實(shí)現(xiàn)時(shí)

考慮下面這個(gè)典型的電子商務(wù)流程。

Payments 服務(wù)生成一個(gè) Order Purchase Completed 事件到 Kafka。現(xiàn)在,Checkout 服務(wù)將消費(fèi)此消息,并生成自己的 Order Checkout Completed 消息,其中包含購(gòu)物車中的所有商品。

然后,所有下游服務(wù)(Delivery、Inventory 和 Invoices)將消費(fèi)該消息并繼續(xù)處理(分別準(zhǔn)備發(fā)貨、更新庫(kù)存和創(chuàng)建發(fā)票)。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

如果下游服務(wù)可以假設(shè) Order Checkout Completed 事件只由 Checkout 服務(wù)生成一次,則此事件驅(qū)動(dòng)流的實(shí)現(xiàn)會(huì)簡(jiǎn)單很多。

為什么?因?yàn)槎啻翁幚硐嗤?Checkout Completed 事件可能導(dǎo)致多次發(fā)貨或庫(kù)存錯(cuò)誤。為了防止下游服務(wù)出現(xiàn)這種情況,它們將需要存儲(chǔ)去重后的狀態(tài),例如,輪詢一些存儲(chǔ)以確保它們以前沒(méi)有處理過(guò)這個(gè) Order Id。

通常,這是通過(guò)常見(jiàn)的數(shù)據(jù)庫(kù)一致性策略實(shí)現(xiàn)的,如悲觀鎖定和樂(lè)觀鎖定。

幸運(yùn)的是,Kafka 為這種流水線事件流提供了一個(gè)解決方案,每個(gè)事件只處理一次,即使當(dāng)一個(gè)服務(wù)有一個(gè)消費(fèi)者 - 生產(chǎn)者對(duì)(例如 Checkout),它消費(fèi)一條消息,并產(chǎn)生一條新消息。

簡(jiǎn)而言之,當(dāng) Checkout 服務(wù)處理傳入的 Payment Completed 事件時(shí),它需要將 Checkout Completed 事件的發(fā)送過(guò)程封裝在一個(gè)生產(chǎn)者事務(wù)中,它還需要發(fā)送消息偏移量(使 Kafka 代理能夠跟蹤重復(fù)的消息)。

事務(wù)期間生成的任何消息將僅在事務(wù)完成后才對(duì)下游消費(fèi)者(Inventory Service)可見(jiàn)。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

此外,位于 Kafka 流開(kāi)始位置的 Payment Service Producer 必須轉(zhuǎn)變?yōu)閮绲龋↖dempotent)生產(chǎn)者——這意味著代理將丟棄它生成的任何重復(fù)消息。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

要了解更多信息,請(qǐng)觀看我的視頻“Kafka 中的恰好一次語(yǔ)義”。

https://www.YouTube.com/watch?v=7O_UC_i1XY0

6事件聚合

當(dāng)你想知道整個(gè)批次的事件已經(jīng)被消費(fèi)時(shí)

在上半部分,我描述了在 Wix 將聯(lián)系人導(dǎo)入到 Wix CRM 平臺(tái)的業(yè)務(wù)流程。后端包括兩個(gè)服務(wù)。一個(gè)是作業(yè)服務(wù),我們提供一個(gè) CSV 文件,它會(huì)生成作業(yè)事件到 Kafka。還有一個(gè)聯(lián)系人導(dǎo)入服務(wù),它會(huì)消費(fèi)并執(zhí)行導(dǎo)入作業(yè)。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

假設(shè) CSV 文件有時(shí)非常大,將工作負(fù)載分割成更小的作業(yè),每個(gè)作業(yè)中需要導(dǎo)入的聯(lián)系人就會(huì)更少,這個(gè)過(guò)程就會(huì)更高效。通過(guò)這種方式,這項(xiàng)工作可以在 Contacts Importer 服務(wù)的多個(gè)實(shí)例中并行。但是,當(dāng)導(dǎo)入工作被拆分為許多較小的作業(yè)時(shí),該如何知道何時(shí)通知最終用戶所有的聯(lián)系人都已導(dǎo)入?

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

顯然,已完成作業(yè)的當(dāng)前狀態(tài)需要持久化,否則,內(nèi)存中哪些作業(yè)已完成的記錄可能會(huì)因?yàn)殡S機(jī)的 Kube.NETes pod 重啟而丟失。

一種在 Kafka 中進(jìn)行持久化的方法是使用 Kafka 壓縮主題。這類主題可以看成是一種流式 KV 存儲(chǔ)。

在我們的示例中,Contacts Importer 服務(wù)(在多個(gè)實(shí)例中)通過(guò)索引消費(fèi)作業(yè)。每當(dāng)它處理完一些作業(yè),就需要用一個(gè) Job Completed 事件更新 KV 存儲(chǔ)。這些更新可以同時(shí)發(fā)生,因此,可能會(huì)出現(xiàn)競(jìng)態(tài)條件并導(dǎo)致作業(yè)完成計(jì)數(shù)器失效。

原子 KV 存儲(chǔ)

為了避免競(jìng)態(tài)條件,Contacts Importer 服務(wù)將完成事件寫到原子 KV 存儲(chǔ)類型的 Jobs-Completed-Store 中。

原子存儲(chǔ)確保所有作業(yè)完成事件將按順序處理。它通過(guò)創(chuàng)建一個(gè)“Commands”主題和一個(gè)“Store”壓縮主題來(lái)實(shí)現(xiàn)。

順序處理

從下圖可以看出,原子存儲(chǔ)如何生成每一條新的 Import-job-completed“更新”消息,并以 [Import Request Id]+[total job count] 作為鍵。借助鍵,我們就可以總是依賴 Kafka 將特定 requestId 的“更新”放在特定的分區(qū)中。

接下來(lái),作為原子存儲(chǔ)的一部分,消費(fèi)者 - 生產(chǎn)者對(duì)將首先偵聽(tīng)每個(gè)新的更新,然后執(zhí)行 atomicStore 用戶請(qǐng)求的“命令”——在本例中,將已完成作業(yè)數(shù)量的值加 1。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

端到端更新流示例

讓我們回到 Contacts Importer 服務(wù)流。一旦這個(gè)服務(wù)實(shí)例完成了某些作業(yè)的處理,它將更新 Job-Completed KVAtomicStore(例如,請(qǐng)求 Id 為 YYY 的導(dǎo)入作業(yè) 3 已經(jīng)完成):

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

Atomic Store 將生成一條新消息到 job-completed-commands 主題,鍵為 YYY-6,值為 Job 3 Completed。

接下來(lái),Atomic Store 的消費(fèi)者 - 生產(chǎn)者對(duì)將消費(fèi)此消息,并增加 KV Store 主題中鍵 YYY-6 的已完成作業(yè)計(jì)數(shù)。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

恰好一次處理

注意,“命令”請(qǐng)求處理必須只發(fā)生一次,否則完成計(jì)數(shù)器可能不正確(錯(cuò)誤增量)。為消費(fèi)者 - 生產(chǎn)者對(duì)創(chuàng)建一個(gè) Kafka 事務(wù)(如上文的模式 4 所述)對(duì)于確保統(tǒng)計(jì)準(zhǔn)確至關(guān)重要。

AtomicKVStore 值更新回調(diào)

最后,一旦 KV 最新生成的已完成作業(yè)計(jì)數(shù)的值與總數(shù)匹配(例如 YYY 導(dǎo)入請(qǐng)求有 6 個(gè)已完成作業(yè)),就可以通知用戶(通過(guò) WebSocket,參見(jiàn)本系列文章第一部分的模式 3)導(dǎo)入完成。通知可以作為 KV-store 主題生成動(dòng)作的副作用,即調(diào)用用戶提供給 KV 原子存儲(chǔ)的回調(diào)。

6種事件驅(qū)動(dòng)的架構(gòu)模式

 

注意事項(xiàng):

  • 完成通知邏輯不一定要在 Contacts Importer 服務(wù)中,它可以在任何微服務(wù)中,因?yàn)檫@個(gè)邏輯完全獨(dú)立于這個(gè)過(guò)程的其他部分,只依賴于 Kafka 主題。
  • 不需要進(jìn)行定期輪詢。整個(gè)過(guò)程都是事件驅(qū)動(dòng)的,即以管道方式處理事件。
  • 通過(guò)使用基于鍵的排序和恰好一次的 Kafka 事務(wù),避免作業(yè)完成通知或重復(fù)更新之間的競(jìng)態(tài)條件。
  • Kafka Streams API 非常適合這樣的聚合需求,其特性包括 groupBy(按 Import Request Id 分組), reduce 或 count(已完成作業(yè)計(jì)數(shù))和 filter (count 等于總作業(yè)數(shù)),然后是副作用 Webhook 通知。對(duì)于 Wix 來(lái)說(shuō),使用現(xiàn)有的生產(chǎn)者 / 消費(fèi)者基礎(chǔ)設(shè)施更有意義,這對(duì)我們的微服務(wù)拓?fù)溆绊懜 ?/li>

7總結(jié)

這里的一些模式比其他的模式更為常見(jiàn),但它們都有相同的原則。通過(guò)使用事件驅(qū)動(dòng)的模式,可以減少樣板代碼(以及輪詢和鎖定原語(yǔ)),增加彈性(減少級(jí)聯(lián)失敗,處理更多的錯(cuò)誤和邊緣情況)。此外,微服務(wù)之間的耦合要小得多(生產(chǎn)者不需要知道誰(shuí)消費(fèi)了它的數(shù)據(jù)),擴(kuò)展也更容易,向主題添加更多分區(qū)(和更多服務(wù)實(shí)例)即可。

原文鏈接:

https://medium.com/wix-engineering/6-event-driven-architecture-patterns-part-1-93758b253f47

https://medium.com/wix-engineering/6-event-driven-architecture-patterns-part-2-455cc73b22e1

分享到:
標(biāo)簽:架構(gòu)
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定