某些请求后,队列createConnection的JMS连接失败

时间:2014-03-03 17:26:07

标签: glassfish jms ejb-3.0

我有一个无状态的ejb,并且我与jms队列建立连接并向其发送消息。
我执行此操作的部分代码:

@Resource(mappedName = "jms/abcd")
private ConnectionFactory abcd;
@Resource(mappedName = "jms/xyz")
private Queue xyz;
 @Override
    public void saveCounter(String protocolName, String serialNumber, String counterName,CounterAction action)
    {
        Connection connection = null;
        Session session=null;
        try
        {
            connection = abcd.createConnection();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer producer = session.createProducer(xyz);

            Message message = session.createMessage();
            message.setStringProperty("serialNumber", serialNumber);
            producer.send(message);
        }
        catch (Exception e)
        {
            logger.error("Sending message to queue", e);
        }
        finally
        {
            try
            {
                if(session!=null){
                    session.close();    
                }
                if (connection != null)
                {
                    connection.close();
                }
            }
            catch (JMSException e)
            {
                logger.warn(e);
            }
        }

    }

我正在使用MDB。消费者代码如下所示:

 @MessageDriven(name = "XXMessageDrivenBean", activationConfig = {
 @ActivationConfigProperty(propertyName = "destinationType",
 propertyValue = "javax.jms.Queue") }, mappedName = "jms/xyz")

 public class CounterMessageDrivenBean {

 ...

     @Override
     public void onMessage(Message message){

        System.out.println("got message: " + message);
            log.debug("got message: " + message);

     }

     .....
 }

我使用来自其他ejb的ejb的功能,通过执行此ejb的依赖注入并调用其方法。它适用于某些请求

但是当我尝试对我的代码进行负载测试时,经过一些像千元的请求之后,代码的crateConnection部分开始失败,异常:

Thread 64518 "httpWorkerThread-38080-1": (state = BLOCKED)
    at com.sun.enterprise.resource.AbstractResourcePool.getResourceFromPool(AbstractResourcePool.java:788)
    at com.sun.enterprise.resource.AbstractResourcePool.getUnenlistedResource(AbstractResourcePool.java:682)
    at com.sun.enterprise.resource.AbstractResourcePool.internalGetResource(AbstractResourcePool.java:624)
    at com.sun.enterprise.resource.AbstractResourcePool.getResource(AbstractResourcePool.java:470)
    at com.sun.enterprise.resource.PoolManagerImpl.getResourceFromPool(PoolManagerImpl.java:248)
    at com.sun.enterprise.resource.PoolManagerImpl.getResource(PoolManagerImpl.java:176)
    at com.sun.enterprise.connectors.ConnectionManagerImpl.internalGetConnection(ConnectionManagerImpl.java:323)
    at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:245)
    at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:175)
    at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:168)
    at com.sun.messaging.jms.ra.ConnectionFactoryAdapter._allocateConnection(ConnectionFactoryAdapter.java:179)
    at com.sun.messaging.jms.ra.ConnectionFactoryAdapter.createConnection(ConnectionFactoryAdapter.java:166)
    at com.sun.messaging.jms.ra.ConnectionFactoryAdapter.createConnection(ConnectionFactoryAdapter.java:148)

显示上面的代码:saveCounter:createConnection

请帮助我理解为什么我的代码开始失败。 我是glassfish应用服务器。

提前致谢

4 个答案:

答案 0 :(得分:1)

人士Himanshu,

首先想到的是为什么你使用无状态ejb来实现这个功能而不是MDB。

关于代码的负面信息是您正在处理JMS连接的打开和关闭。

如果您使用的是MDB,则JMS连接处理由MDB本身处理。 此外,您将打开一个JMS连接池,可以轻松调整。 因此,您不应该遇到报告的相同问题。

答案 1 :(得分:1)

您可以尝试关闭MessageProducer对象。您的代码看起来非常适合关闭会话和连接,但您实际上并没有关闭生产者。 MessageProducer javadoc建议调用close()。您可以在producer.close();之后立即拨打producer.send(message);

另外,关于finally块的小建议 - 如果session.close()抛出异常,你将无法关闭连接。您也可以尝试在try / catch块中包装该调用:

 finally
    {
        try
        {
            if(session!=null){
               try {
                  session.close();    
                } catch(JMSException e) { }
            }
            if (connection != null)
            {
                connection.close();
            }
        }
        catch (JMSException e)
        {
            logger.warn(e);
        }
    }

希望这有帮助!

答案 2 :(得分:1)

我使用非常相似的代码每天处理200,000-300,000 trx并且没有遇到任何问题。我在这里分享代码: ...

Connection connection;
Session session = null;
MessageProducer messageProducer;
try {
    connection = connectionFactory.createConnection();

    session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    messageProducer = session.createProducer(queue);
    TextMessage message = session.createTextMessage();

    for (String msgKey : messages.keySet()) {

        message.setText(messages.get(msgKey));
        // logger.debug("Sending message to Queue: "
        // + message.getText());
        messageProducer.send(message);
    }
} catch (JMSException e) {
    logger.info("Error " + e);
    e.printStackTrace();
}

...

我可以从您的代码中看到的唯一区别是我在try块之外声明了MessageProducer。试着看看它是否有所作为。

答案 3 :(得分:0)

我发现关闭连接,也关闭了会话和制作人。因此,没有与开放资源相关的问题。

我发现的问题是,我们对jms施加了太大的负担,就像每小时缺少一次。因此,jms服务无法处理如此多的负载。