2017-06-19 56 views
0

我正在使用一箇中等大小的Web應用程序,它分爲幾個微服務。目前,服務彼此溝通的方式是不可持續的混亂,所以我正在研究其他解決方案。用於內部微服務通信的Apache Kafka;在什麼級別將主題映射到事件?

看起來非常吸引我的一種方法是使用消息代理,其中每個服務都會發送和收聽消息。 Apache Kafka引起了我的注意,並且看起來像是一個非常有前途的軟件選擇。

但是,我不確定我會如何使用卡夫卡的主題,或者更具體地說,在什麼級別將事件映射到主題。我已經確定了三個主要粒度級別,如下所述。

出於演示目的,請考慮一個假設的在線商店,該商店由許多服務組成,如ShoppingCart,Billing和Shipping。

整個應用程序使用一個主題

單個主題,例如my-app-events,用於傳送服務發送和接收的所有事件。一個事件可能如下所示:{"from": "shopping-cart", "name": "PRODUCT_ADDED", "payload": {"product_id": 137}}

每個微服務使用它自己的主題

單獨的主題,例如shopping-cart-events,billing-eventsshipping-events等被使用。現在shopping-cart-events主題中的事件可能看起來像{"name": "PRODUCT_ADDED", "payload": {"product_id": 137}}

每個事件類型使用自己的主題

這裏每個可能的消息都有自己的主題。我認爲將主題名稱中的事件製作者包含在內是有意義的,因此可以將主題稱爲shopping-cart.product-added。在這種情況下,消息內容將僅僅是有效載荷,例如, {"product_id": 137}


我希望我能在三種方法之間做出明顯區別。你有什麼建議?您是否以這種方式成功使用過Kafka(或任何其他消息中介)?每種解決方案有哪些優勢和缺陷?

回答

2

整個應用程序使用一個主題。

我真的看不出有什麼好處這個

每個微服務使用它自己的主題。

如果您需要在發生在同一個實體上的事件之間進行排序,這是一條路。例如諸如購物車,產品添加,購物車產品之類的事件爲了一致性應該保留相同的購物車ID以保持排序。這意味着他們去了同一個分區,因此也是同一個主題。

每種事件類型都使用自己的主題。

這種方法的好處是類型安全,因爲每個主題中只有一種類型的消息,所以反序列化和下游處理的錯誤更少。但是,您無法保持發生在同一個實體上的不同事件之間的順序。總而言之,我會建議每個實體類型有一個主題(實體是事件發生的事情,以DDD術語來說,這將被稱爲集合)。購物車。如果您的服務如此細緻,以至於每個服務只有一個實體類型,那麼這可歸結爲每個服務一個主題。

+0

非常感謝你的洞察力@ michal! –

0

關於卡夫卡:

首先考慮,如果你真的想運行卡夫卡作爲你的消息代理。

卡夫卡速度很快,但背後隱藏着許多細微之處,使得它難以使用。如果您只運行Web服務,也許其他的pub/sub技術可能更合適。

卡夫卡本身就是一個話題,所以我會在你應該更仔細地考慮什麼時做簡短的介紹。這是自以爲是,從我自己的進行技術經驗:

  • 你不能輕鬆地閱讀,瀏覽或在你的信息刪除消息,好運氣找到一個單一的越野車消息,如果你不進行適當的記錄
  • 分區系統需要額外的管理工作,因爲它們使用與用於公共庫的主題不同的服務器API。如果你只運行一些消費者,你可能會對每個主題的單個分區都很好。
  • 偏移提交功能:當您希望確保沒有錯過任何一條消息時,這一點非常重要,因此您可能希望禁用自動提交功能並執行手動驗證偏移量
  • 除非您保證冪等性,否則您將擁有要自己實現一個'精確一次'的功能,因爲Kafka'至少有一次':您不想再次扣留該客戶兩次,或者再次發運您的產品,或者因爲對卡夫卡的重播功能的錯誤處理而給客戶帶來了垃圾郵件。
  • kafka消費者類通常會'阻止'直到他們有事件發生,如果您運行單線程進程並需要監視其他東西,這可能並不理想......您最終可能會投票(),但這些實現可能會根據您的客戶端庫而有所不同。
  • 卡夫卡最好的監控工具是雅虎製作的,並且是社區維護的。卡夫卡官方的管理和監測工具很糟糕,可笑的是。
  • 卡夫卡仍然不成熟,我不會說這是生產安全的,但從0.10起事情會更好。
  • 我現在不知道,但是,幾個月前,大部分客戶端JS庫都已經過時(Kafka < = 0.8),記錄不準確或使用痛苦。

的話題架構:

首先,@Michal Borowiecki給了這些值得考慮的一些好點。

根據我自己的經驗,您會發現每個事件類型都有一個方便的主題:每當您打開主題時,您都會知道您會在其中找到什麼。

如果你需要消費不同的事件類型,你可以通過同時消費多個主題來做到這一點(小心,卡夫卡消費者並不是很擅長平衡,如果你消費了5個主題,而且有一個被淹沒,你可能會陷入停滯消耗所有從那裏傳來的信息,而不會從其他話題獲得任何數據,直到事情冷靜下來......反應性可能會受到影響)。

每個事件類型的一個主題不應該阻止您爲單個事件類型擁有不同的事件名稱,並且如果您的服務丟棄/過濾事件就沒有問題。

例如:您可以擁有一個事件類型'User Connexion'並且具有'已登錄'和'已註銷'作爲該事件類型的事件名稱,全部在同一主題內(用戶連接) - 事件名稱爲嵌入到事件的元數據中。這是有道理的,因爲您要確保按順序處理這些消息:註銷必須先於註銷,並且註銷的用戶不能執行特權操作。

如果你想對事件如何相關的更全面概述,或重放基於集羣範圍內的秩序的事件,你可能會實施相關IDS矢量時鐘間隔樹時鐘和適當的信息存儲,以便於操作和檢查(例如:將主題轉儲到MongoDB上...)。另外,如果您使用MongoDB,請查看MongoDB的findAndModify()功能,這將允許您使用唯一的羣集ID持續標記每條消息。