2012-10-12 66 views
1

我有一個帶有Netty端點的駱駝實例,它將許多傳入請求合併到一個接收器中。更具體地說,這是一個Web服務,每個傳入的SOAP請求都會在駝峯子系統中生成一個Producer.sendBody()。每個請求的處理都涉及不同的路由,但它們都將在單個Netty端點中發送到下一級服務器。一切都很好,只要我一次只有少量的傳入請求。如果我開始有超過100個併發請求,不過,我得到這個異常:駱駝ServicePool與Netty一起使用時的邏輯

java.lang.IllegalStateException: Queue full 
    at java.util.AbstractQueue.add(AbstractQueue.java:71) ~[na:1.6.0_24] 
    at java.util.concurrent.ArrayBlockingQueue.add(ArrayBlockingQueue.java:209) [na:1.6.0_24] 
    at org.apache.camel.impl.DefaultServicePool.release(DefaultServicePool.java:95) [camel-core-2.9.2.jar:2.9.2] 
    at org.apache.camel.impl.ProducerCache$1.done(ProducerCache.java:297) ~[camel-core-2.9.2.jar:2.9.2] 
    at org.apache.camel.processor.SendProcessor$2$1.done(SendProcessor.java:120) ~[camel-core-2.9.2.jar:2.9.2] 
    at org.apache.camel.component.netty.handlers.ClientChannelHandler.messageReceived(ClientChannelHandler.java:162) ~[camel-netty-2.9.2.jar:2.9.2] 
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:296) ~[netty-3.3.1.Final.jar:na] 

這是從的二手由Netty的組件DefaultServicePool到來。 DefaultServicePool使用ArrayBlockingQueue作爲隊列的後端,並將其設置爲100個生產者的默認容量。它出於性能原因使用服務池,以避免不斷創建和銷燬經常重用的生產者。很公平。不幸的是,我沒有得到如何實施的邏輯。

這一切都始於ProducerCache::doInAsyncProducer,開頭爲doGetProducer。所述方法嘗試從池中生產者acquire,如果失敗,則使用endpoint.getProducer()創建新的生產者。然後確保服務池使用pool.addAndAcquire。完成後,它返回到調用函數。 doInAsyncProducer在完成之前完成它,在這種情況下它會調用done處理器。此時,我們完成了交易處理,因此它使用pool.release

將生產者釋放回池中。這裏是橡膠撞擊道路的地方。 DefaultServicePool::release方法使用add將生產者插入到ArrayBlockingQueue後端。這是我的java.lan.IllegalStateException來自的地方。

爲什麼?那麼,讓我們看看一個用例。我有101個同時傳入的請求。它們中的每一個大致在同一時間點擊Netty端點。第一個創建容量爲100的服務池,但是它開始時是空的。實際上,101個請求中的每一個都會從endpoint.getProducer創建一個新的Producer;每個人將驗證他們沒有超過服務池的容量(這是空的);並且每個將繼續發送到服務器。完成後,它會嘗試執行pool.release。前100名將成功,因爲池容量尚未達到。第101個請求將嘗試添加到隊列中並失敗,因爲隊列已滿!

是嗎?如果我正確閱讀,那麼只要有超過100個同時請求,此代碼就會失敗。我的服務需要支持多達10,000個同時請求,所以這只是不會飛。

這似乎是一個更穩定的解決方案可能是:

  1. 預分配期間acquire所有100名製片人於初始化
  2. 阻塞,直到生產者可用
  3. 絕對不要創建自己的非-pool生產者如果使用ServicePool

在此期間,我想節流傳入的請求。

我對這個問題的期望是學習如果我正確地閱讀這個邏輯,看看它是否可以改變。或者,我用錯了嗎?有沒有更好的方法來處理這種類型的事情?

回答