現在、JBoss AS7 で断続的な例外が発生していますが、残念ながらまだ再現できません。
現在、基本的に JMS メッセージのプロデューサー/コンシューマーとして設定されている 2 つのアプリケーションを実行しています。デフォルトの HornetQ 設定と 5 つの MDB のプールを使用しています。
両方のアプリケーションが正常に動作し始め、期待どおりにメッセージを送受信します。しかし、しばらくすると、すべての MDB がロックされ (それぞれにメッセージが表示されますが、処理が完了しません)、その後 JBoss がハングし、10 分ごとに次のメッセージが表示されます。
[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
jarvana の JBoss コードから、セマフォを取得できない場合にこのエラーが設定されているように見えます。
/**
* 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 のタイムアウトを設定するその他の方法についての提案を喜んで受け入れます。
どんな助けでも大歓迎です。
御時間ありがとうございます。
編集:
そのため、MessageListener を instance-acquisition-timeout より長くスリープ状態にするだけで、最終的に問題を再現することができました。以下はテストコードです。
<!-- 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);
}
}
}