2017-08-27 150 views
2

我創建其中前端服務推消息到卡夫卡請求「主題並監聽另一「響應」主題對於一些下游後端消費者(實際上是一個複雜的系統中的系統,該系統最終推回卡夫卡),對「請求」消息進行處理,最終推到「響應」主題。匹配卡夫卡消費者和生產者分區

我想弄清楚最優雅的方式,以確保消費者偵聽適當的分區並接收響應,並且後端推到前端使用者正在偵聽的分區。我們總是需要確保響應發送給產生初始消息的相同消費者。

我有兩個解決方案,截至目前,但也不是特別令人滿意。任何想法或想法將不勝感激:

  1. 有每個前端決定它將偵聽哪個分區,並通過該消息傳遞給'request'主題的分區。當後端處理完成時,它將查看消息的分區成員並推送到相應的分區。這裏最直接的問題是如何協調前端服務,以便每個分區具有均勻分佈(隨機分配?)。
  2. 每個消息具有相關性ID,一個GUID,所以爲每個請求我們的前端,我們可以開始監聽基於散列的GUID來分區的總數分區然後按消息發送到所述「請求」的主題。後端會查看關聯ID以確定要推送到的適當分區。這裏的一個問題是,對於每個請求,前端必須在新分區上建立新的使用者(這裏是否有開銷?),並且可能會在同一分區上有多個活動使用者,以及跨多個活動使用者許多分區。
  3. 有同等數量的消費者和分區的一個消費羣,然後用類似的方法(1),但允許卡夫卡去應付這是消費者在哪個分區。但是,我們需要弄清楚重新平衡發生時會發生什麼情況,特別是對於已經在後端運行的消息(因爲可能所有分區都可能發生變化?)。

這似乎應該是一種常見的模式,所以我想知道別人怎麼解決這個問題。

回答

3

請不要使用消費者手動分配的分區。它會變得非常混亂,而且很難擴展。

而不是分區,您可以使用每個前端使用者的主題。每個前端服務都會生成一條消息,其中包含前端服務的標識request主題。然後後端消費該消息,並根據該id產生對特定unique-front-end-service-response主題的響應消息。 如果您有一個固定數量的前端服務,它可能是一個很好的解決方案。可能的缺點是每次您想添加新的前端服務時都會創建一個新的主題。但是,維護比手動分區分配要容易得多。

另一種可能的解決方案可能是使用不同的工具。如果卡夫卡不是強制性的,請重新考慮您的要求並進行研究。可能有一種工具比卡夫卡更適合您的需求。

+0

謝謝 - 每個前端的單個主題似乎可能是一個可行的解決方案。我們在後臺大量使用Kafka,但我想我們總是可以找到與前端直接通信的其他方式,而不是在後端處理完成時通過Kafka進行通信。 – David

0

有時響應不回到原來的請求的應用程序,如果有可能直接通過發送卡夫卡響應消息到卡夫卡連接器,通過網絡掛接,WebSocket的,現直接對外交貨響應用戶的請求,或短信回覆原始用戶。

如果你只是想做SOAP或REST風格的RPC,那麼只需使用HTTP而不是Kafka,因爲這是一種經過驗證的模式。

+0

在我們的例子中,前端是一個HTTP服務,所以同一個實例需要響應我們後端返回的內容。 – David

+0

因此,以您的HTTP服務的URL作爲密鑰發佈Kafka請求消息。當後端Kafka消費者想要發送響應時,它應該發佈到具有與密鑰相同的URL的響應主題。然後,HTTP/webhook的Kafka連接器將獲取響應消息,並執行HTTP回發原始HTTP服務(可能在稍微修改了URL的響應中)。因此,從原始Web服務的角度來看,它是kafka請求/ http響應。如果您想一次支持多個請求,只需在URL中添加一個correlationID即可 –

0

一個優雅的方法是在後端製作者中使用分區功能,並使用手動分區分配assign使前端消費者只聽有趣的分區。

更詳細:

在前端生產,你生產的「請求」消息,「請求」話題之前,設置消息鑰匙前端客戶端ID(它需要獨一無二)。

在後端消費,有沒有必要做手工分區的分配,只是用subscribe認購的request話題。但值得注意的是,當您收到「請求」消息並處理該消息時,請不要丟失消息密鑰並保存。因爲它確定請求來自哪裏。

在後端生產者中,當您完成請求過程時,您將生成一條回覆消息,並將響應消息鍵設置爲您保留在上面的前端客戶端ID。你還需要定義一個分區函數(一個散列函數,將客戶機ID映射到分區號)。使用分區功能做send()

在前端消費者中,您需要使用assgin()方法來偵聽特定分區。但是如何知道應該聽哪個分區?只需使用它的client-id(它將在同一個客戶機上相同)和上面定義的相同散列函數來計算你應該聽的分區號。