2015-02-09 117 views
0

我需要幫助找出最佳解決方案以下設計問題。與駱駝異步消息處理

我有一個由我們的用戶使用的單個前端服務器。他們提交應該異步運行的任務,並在完成後發送電子郵件。該任務可以調用外部API並更新其中的內容。有一些帳戶(不會被用戶帳戶混淆)與API相關聯。用戶將爲特定帳戶運行任務,並且一旦該帳戶在執行api更新時進行操作,則需要等待使用相同帳戶更新API的其他任務。請注意,使用不必等待,他們可能會提交相同(api)帳戶的許多任務。這是負責將任務放入隊列的系統。 隊列將被一羣服務器監聽,一旦帳戶被釋放,下一個任務將被其他服務器接收。因此,我們提交了多個任務,爲多個帳戶更新api。 我正在尋找Apache Camel作爲我的解決方案,前端將在總線上提交任務,其中一臺服務器將檢測到它。但是,如果有多個任務來自同一個帳戶,只有一個可以像上面解釋的那樣執行,我想保留隊列中某個地方的其他任務(我不知道該怎麼做)以及一旦帳戶被釋放,下一條消息應該由集羣中的一臺服務器選取。 關於更好的解決方案的任何建議,甚至不知道駱駝是否是這類問題的最佳解決方案。我是新來的這種異步設計問題。

回答

0

駱駝非常適合這種設計。我們在非常相似的場景中使用它,它提供了一切你需要的東西(轉換,異步調用等)。

我的建議:

每個API賬戶1個隊列
  1. 使用JMS服務器
  2. 創建標準的服務來獲取用戶通話(如SOAP/HTTP),並把右隊列中的任務(使用http://camel.apache.org/recipient-list.html模式)
  3. 爲隊列創建偵聽器(1個偵聽器,每個隊列有1個線程?maxConcurrentConsumers=1)。您可以在setApplicationContext事件動態創建它們例如
+0

感謝潮流,我們有大約3000個賬戶。我不確定配置3000個隊列和3000個監聽器的效率如何。想法? – Kaunteya 2015-02-09 21:23:50

0

我認爲你可以做到這一點的設計,2個隊列,以及兩個企業集成模式:一個aggregatorconcurrent consumers

第一個隊列是您的作業提交的地方。我們稱之爲submit。這裏的工作是通過accountId彙總工作,並將其分批發送給另一個隊列1

我們需要運行僅一個節點上的路線(我們使用master:組件)現在

from("master:myyapp:mq:queue:submit) 
    .aggregate(header("accountId"), new SimpleAggregator()).completionSize(1) 
    .inOut("mq:queue:process"); 

,您只需將作業發送到process隊列,這可以通過任何處理集羣中的服務器。這裏的關鍵是我們正在使用inOut模式,這是一個請求 - 回覆模式(您的jms必須支持這種模式)。

我相信這應該解決在任何時候只有一個工作應該在給定的賬戶ID上運行的需求(但是你應該明智地在某些測試中先模擬這個)。

0

@vikingsteve有一個很好的答案,但我認爲它值得看看idempotent consumer這可能更適合用例。

的主要原因是該aggregator用於批量了許多交流在一起,而將確保它只處理單個項對於給定的上下文中(此使用JpaRepo存儲的狀態)

RouteBuilder會是這個樣子:

// api endpoint 
from("jetty:http://localhost:8080/api/submit") 
    .inOnly("jms:queue:submit") 
    .process(new Processor() { 
     // set the response message 
    }); 

// this implements the async processing, but will only process 
// a single accountId at a time 
from("jms:queue:submit") 
    .idempotentConsumer(
     header("accountId"), 
     jpaMessageIdRepository(lookup(JpaTemplate.class), PROCESSOR_NAME)) 
    .inOut("jms:queue:process"); 

,並使用此駱駝配置有10名JMS消費者(這將使你在並行運行10個操作)

<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration"> 
    <property name="autoStartup" value="true" /> 
    <property name="concurrentConsumers" value="10" /> 
    <property name="connectionFactory" ref="pooledConnectionFactory" /> 
</bean> 
+0

嗨,我很感謝你向我們展示這種模式。問題 - 這將允許多個節點同時處理任務(針對不同的帳戶ID)? – vikingsteve 2015-02-10 08:14:15

+0

是的。如果您在JMS組件上說10個消費者,那麼它們將分別並行運行。如果他們擊中了已在冪等商店註冊的密鑰,它將停放交易所並繼續前進 – stringy05 2015-02-10 22:10:02

+0

好的,但是它應該在終端擁有'master:'嗎?這將導致上述邏輯僅在一個節點上運行。 – vikingsteve 2015-02-10 22:23:15