2012-10-19 84 views
3

我目前在JBoss AS7中出現一個間歇性異常,很遺憾,我現在還不能重現。JBoss AS7在MDB鎖定後掛起

我們目前正在運行兩個基本上被設置爲JMS消息的生產者/消費者的應用程序。我們使用默認的HornetQ配置和5個MDB池。

兩個應用程序都開始正常工作,按預期發送和接收消息。但是,一段時間後,所有多邊開發銀行被鎖定(它們每收到一條消息,但沒有完成處理)和JBoss掛起一段時間後顯示每隔十分鐘以下消息:

[org.jboss.ejb3.invocation] (Thread-21081 (HornetQ-client-global-threads-1636833629)) JBAS014134: EJB Invocation failed on component MyMessageListener for method public abstract void javax.jms.MessageListener.onMessage(javax.jms.Message): javax.ejb.EJBException: JBAS014516: Failed to acquire a permit within 10 MINUTES 

從JBoss的代碼jarvana,它似乎如果信號量無法獲取,則會設置此錯誤:

/** 
* Get an instance without identity. 
* Can be used by finders,create-methods, and activation 
* 
* @return Context /w instance 
*/ 
public T get() { 
    try { 
     boolean acquired = semaphore.tryAcquire(timeout, timeUnit); 
     if (!acquired) 
      throw new EJBException("Failed to acquire a permit within " + timeout + " " + timeUnit); 
    } catch (InterruptedException e) { 
     throw new EJBException("Acquire semaphore was interrupted"); 
    } 
... 

問題是,爲什麼MDB被鎖定?他們不應該超時並繼續處理嗎?我在standalone.xml文件中將超時設置爲5分鐘,但他們從來沒有超時。

<session-bean> 
<stateless> 
    <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/> 
</stateless> 
<stateful default-access-timeout="5000" cache-ref="simple"/> 
<singleton default-access-timeout="5000"/> 
</session-bean> 

有誰知道會發生什麼?

我也非常樂意接受有關如何模擬問題或其他方式設置MDB超時的任何建議。

任何幫助,將不勝感激。

謝謝你的時間。

編輯:

所以,我終於能夠通過發送消息監聽睡比實例採集超時不再是簡單重現該問題。以下是測試代碼:

<!-- standalone.xml --> 
<strict-max-pool name="mdb-strict-max-pool" max-pool-size="5" instance-acquisition-timeout="30" instance-acquisition-timeout-unit="SECONDS"/> 

MDB:

@MessageDriven(name = "TestMDB", activationConfig = { 
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), 
    @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/myQueue"), 
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")//, 
    }) 
public class TestMDB implements MessageListener { 

private final static Logger LOGGER = Logger.getLogger(TestMDB.class 
     .toString()); 

@Resource 
private MessageDrivenContext ctx; 

private final static int sleepingTime = MyProperties.SLEEP_MILLISECS; 

/** 
* @see MessageListener#onMessage(Message) 
*/ 
public void onMessage(Message rcvMessage) { 
    ObjectMessage msg = null; 
    Future<String> future = null; 
    MyResource res = null; 

    try { 
     if (rcvMessage instanceof ObjectMessage) { 
      msg = (ObjectMessage) rcvMessage; 
      res = (MyResource)msg.getObject(); 

      LOGGER.info("Received resource: " + res); 
      Thread.sleep(sleepingTime); 
      LOGGER.info("Released resource: " + res); 
     } else { 
      LOGGER.warning("Message of wrong type: " 
        + rcvMessage.getClass().getName()); 
     } 
    } catch (JMSException e) { 
     throw new RuntimeException(e); 
    } catch (InterruptedException e) { 
     throw new RuntimeException(e); 
    } 
} 
} 
+0

關於jboss的相關文章(未解決),https://developer.jboss.org/message/794455 – Gab

回答

3

看來,如果這種行爲是可以預期的,但問題可能是應用相關的。

下面是問題的一個總結:

  1. 我們有一個MDB實例;
  2. MDB從隊列Q1接收消息;
  3. 我們發送消息給隊列Q1;
  4. MDB嘗試處理它,但由於我們模擬了一個比實例獲取超時更長的進程,HornetQ超時,我們得到了一個例外:「無法在X MINUTES中獲得許可證」;
  5. 不幸的是,MDB繼續處理和睡眠時間
  6. 如果我們的MDB發佈之前停止JBoss的,應用程序將繼續它的處理後,只有被釋放,因爲消息是持久的,它知道我們沒有完成MDB #onMessage方法;
  7. 但是由於我們還沒有確定應用程序問題,鎖再次發生,我們得到一個異常循環;

理想的解決方案是發現爲什麼MDB被鎖定,但在此之前,由於應用程序已經投入生產,我們需要一個回退計劃。我相信一個解決方案是在我們到達Hornet的等待超時(或事務超時 - @ActivationConfigProperty(propertyName =「transactionTimeout」,propertyValue =「30」))後中斷MDB線程,但似乎沒有在JBoss AS7中做一個簡單的配置(還沒有)。

可悲的方法是定時執行MDB線程,並在onMessage方法中強制中斷。這可以通過ExecutorService輕鬆實現(http://stackoverflow.com/questions/6460664/how-can-i-interrupt-method-execution-by-time)

對於遇到同樣問題的任何人,我發現在網絡上一些類似的討論:

http://bryanpendleton.blogspot.com.br/2009/05/timertask-exception-handling.html https://community.jboss.org/thread/162822

希望這有助於。

並希望我可以檢測到應用程序的任何錯誤。

+2

Isabelle,你是否設法解決了這個問題? – jguilhermemv

0

我也遇到過這個問題,最後我們通過下面的命令檢查了JBoss的線程,發現了根本原因。

jstack $pid 

而我們發現一個線程死鎖。在我們修復僵局之後,JBoss再也沒有停下來。