簡體   English   中英

從隊列中選擇性讀取-自定義MSMQ服務,ESB還是其他內容?

[英]Selective Reading From a Queue--Custom MSMQ Service, ESB, or Something Else?

尋找一些想法/模式來解決系統的設計問題,我將很快開始工作。 毫無疑問,我將需要使用某種消息傳遞(可能是MSMQ)在系統的某些區域之間進行通信。 我不想重新發明輪子,但是同時我想確保我使用正確的工具來完成這項工作。 我一直在研究和閱讀NServiceBus,它的功能給我留下了深刻的印象-但是我不確定它是否適合我要實現的目標。

這是(希望)對系統需要執行的非常簡單和概念性的描述:

我有一個客戶端可以向其發送消息的服務。 服務是“一勞永逸”的-客戶端獲得的最多回報可能是成功或失敗(成功是因為已收到消息)。

每個消息的處理/處理都是不平凡的,可能會占用大量系統資源。 因此,只能同時處理X條消息,其中X是可配置的值(基於系統規格等)。 傳入的消息將存儲在隊列中,直到輪到他們處理。

對於每個客戶端,必須按順序處理消息(FIFO)。 但是,某些客戶端可能會連續發送許多消息(數千個或更多),例如,如果它們在一段時間內失去連接。 因此,必須在所有客戶端之間以循環方式處理郵件-不允許客戶端進食,也不允許客戶端餓死。 因此,系統要么必須能夠查詢特定客戶端的隊列,要么必須為每個客戶端創建單獨的隊列(自動,因為在編譯時不會知道客戶端),然后輪流從它們中拉出。

我目前的想法是,我真的只需要使用原始MSMQ,創建一個服務來接受消息並將它們寫入一個或多個隊列,然后創建一個過程以從隊列中讀取消息並處理/處理它們。 但是,使用NServicebus之類的產品所獲得的可靠性,審核性,可伸縮性和易於配置的外觀非常吸引人。

ESB是工作的錯誤工具嗎? 還有其他我應該關注的技術或模式嗎?

更新

一些澄清。

關於“按順序”處理消息-在單個客戶端的上下文中,絕對需要按接收順序對消息進行處理。 解釋其確切原因很復雜,但這是一個嚴格的要求。 我忽略了提及每個客戶端只能同時處理一條消息的情況。 因此,即使有10個工作線程,並且只有一個客戶端等待處理消息,一次只處理其中一個消息-無需擔心競爭狀況。

我相信使用香草MSMQ通常可以做到這一點-您可以在隊列中擁有消息列表,並始終以最早的消息為准。

我還想闡明循環訂購的用例。 在此示例中,我有兩個客戶端(A和B)發送消息,並且只有一個工作線程。 所有隊列均為空。 客戶端A在一夜之間失去連接,因此在上午8點向該服務發送1000條消息。 這些消息排隊,工作線程使用最早的消息並開始處理它。 在處理此第一條消息時,客戶端B將消息發送到服務中,該消息被排隊(如上所述,可能在單獨的隊列中)。 當客戶端A的第一條消息完成處理時,邏輯應檢查客戶端B是否有一條消息(這是客戶端B的“轉彎”消息),並且由於找到了一條消息,因此接下來進行處理。

如果客戶端B在此期間未發送消息,則工作人員將一次繼續處理客戶端A的消息,並在處理后始終檢查是否其他客戶端隊列中包含等待消息,以確保沒有客戶端被餓死。

我仍然覺得ESB之間可能不匹配,而這個問題是ESB旨在促進服務之間的通信。 我試圖實現的是消息傳遞/通信與選擇性排隊系統的結合。

使用像NServiceBus這樣的ESB似乎是解決您的問題的好方法。 但是根據您的概念描述,有一些事情需要考慮。 讓我們逐步使用NServiceBus作為可能的ESB解決方案來滿足您的要求:

我有一個客戶端可以向其發送消息的服務。 服務是“一勞永逸”的-客戶端獲得的最多回報可能是成功或失敗(成功是因為已收到消息)。

使用NServiceBus可以輕松完成此操作。 您可以從客戶端Bus.Send(Message)。 如果您的客戶需要答案,則可以使用Bus.Return(ErrorCode)。 您提到“成功是收到消息”。 如果您使用像NServiceBus 這樣的 ESB,則由消息傳遞平台來傳遞消息 因此,如果您的Bus.Send沒有引發異常,則可以確保消息已正確發送。 因此,您可能不必將成功/失敗消息發送回客戶端。

每個消息的處理/處理都是不平凡的,可能會占用大量系統資源。 因此,只能同時處理X條消息,其中X是可配置的值(基於系統規格等)。 傳入的消息將存儲在隊列中,直到輪到他們處理。

使用NServiceBus時,可以通過設置“ NumberOfWorkerThreads”選項來配置輔助線程的數量。 如果您的服務器具有多個核心/ CPU,則可以使用此設置來平衡工作負載。

對於每個客戶端,必須按順序處理消息(FIFO)。

根據您的要求,這可能會引起問題。 如果ESB有許多線程處理消息 ,則通常不會保證按順序處理消息。 對於NServiceBus,您可以從客戶端向總線發送一系列消息, 這些消息將按順序進行處理。 另外,您可以使用Sagas解決一些順序消息傳遞問題。

但是,某些客戶端可能連續發送許多消息(數千個或更多),例如,如果它們在一段時間內失去連接

使用ESB解決方案時,您的服務器不必為客戶端工作而啟動。 客戶端仍然可以發送消息,並且服務器一旦恢復在線狀態,便會開始對其進行處理。 這是一個小介紹。

因此,必須在所有客戶端之間以循環方式處理郵件-不允許客戶端進食,也不允許客戶端餓死。

這不是問題,因為您已決定使用消息:)

因此,系統要么必須能夠查詢特定客戶端的隊列,要么必須為每個客戶端創建單獨的隊列(自動,因為在編譯時不會知道客戶端),然后輪流從它們中拉出。

您能對此進行擴展嗎? 我不確定您對此的設計。

因此,系統要么必須能夠查詢隊列中的特定客戶端,

使用游標在MSMQ隊列中搜索來自特定客戶端的消息可能效率低下並且無法擴展。

或為每個客戶端創建單獨的隊列(自動,因為在編譯時不會知道客戶端),然后輪流從它們中拉出。

MSMQ無法自動創建隊列。 必須先將所有消息發送到已知隊列。 但是,您自己的自定義調度程序服務可以按需創建新隊列,並將消息副本放入其中。

[[我避免說“移動”消息,因為您無法使用應用程序代碼來執行此操作; 您只能使用原始數據閱讀消息並創建新消息。 例如,在使用“源日記帳”時,這種區別很重要。]]

干杯

約翰·布雷克威爾

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM