2011-06-27 65 views
0

當我通過Servlet接收/使用來自JMS隊列的消息時,出現性能問題。
對Servlet的簡單請求需要10秒鐘才能執行QueueSession對象的close方法(以關閉JMS資源)。 如果我連續多次使用Servlet,close方法需要20-30秒。 並行執行(一次請求10個)queueConnection.close()需要6-7分鐘。 在一個同步塊中,我回到了執行queueConnection.close()的20-30秒的值。Glassfish關閉延遲的JMS隊列連接/會話資源。 JMS連接池如何工作?

我感覺Servlet線程從池中獲取相同的QueueConnection。

不應該這樣,以便Servlets從池中獲取免費連接資源?

可以對JMS連接工廠的池設置進行如下設置: 初始和最小池大小,最大池大小,池大小數量,空閒超時,最長等待時間。 我已經嘗試了Pooling的幾個設置,但沒有得到更好的結果。

我想我還必須實現自己池化我從OpenMQ連接池獲得的連接,是嗎?

我有超過40,000條消息在隊列中,並且消息被參數化(使用消息選擇器),是關閉方法延遲(釋放JMS Ressources)的原因? 如果我從基於文件的持久性切換到基於jdbc的持久性,以獲得更好的性能,它會影響嗎?

在下面的答案中建議使用OpenMQ的UMS組件。 UMS是有用的,但我需要使用消息選擇器,我認爲這不受UMS支持。

謝謝!

編碼:

public class MessageReceiver { 
... 
public MessageReceiver(){ 

     queueName = "myQueuedestination"; 
     jndiContext = new InitialContext(); 
     queue = (Queue) jndiContext.lookup(queueName); 
     queueConnectionFactory = (ConnectionFactory) jndiContext 
       .lookup("myQueueconnectionfactory"); 
     queueConnection = queueConnectionFactory.createConnection(); 
     queueConnection.start(); 
} 
... 
public String receive(String KEY, String keyValue) throws Exception {  


    String returnMessage = null; 
    String messageSelector = getMessageSelector(KEY, keyValue);       

    Message m = null;  


    QueueSession queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); 
    QueueReceiver queueReceiver = queueSession.createReceiver(queue, messageSelector);     

    m = queueReceiver.receiveNoWait(); 

    if (queueSession != null) { 
     try { 
      queueSession.close(); 
     } catch (JMSException e) { 
      logger.info("There was an error closing the queueSession"); 
      e.printStackTrace(); 
     } 
    }   
    queueSession = null; 

    if (m != null && m instanceof TextMessage) { 
     returnMessage = ((TextMessage) m).getText();     
    } 

    return returnMessage; 
} 
... 
... 
} 

的Servlet

... 
public void init(ServletConfig config) throws ServletException { 
... 
messageReceiver = new MessageReceiver(); 
... 
} 

protected void doGet(HttpServletRequest request, 
     HttpServletResponse response) throws ServletException, IOException  
{ 
... 
... 

       synchronized (this) 
       { 
        message = messageReceiver.receive(KEY,  keyValue); 
       } 

... 
... 

} 

回答

1

IMO如果你覺得你必須消耗在servlet中可能會有一些錯誤設計的消息......我最強烈建議您在MDB,消息驅動的Bean中接收消息。這是Java Enterprise中爲了使用消息而創建的結構。

+0

我想避免使用MessageListener(消息驅動Bean),因爲我需要一個簡單的應用程序。我希望通過URL(如http:// localhost:port/myServlet)通過鍵(JMS Property/messageSelector)檢索消息?mykey = abcdef –

+0

OpenMQ的UMS組件(GlassFish的JMS實現)可能是您需要的全部那種情況 - 請查看http://mq.java.net/4.3-content/ums/umsMain.html。 – fvu

+0

我需要使用消息選擇器,但這不受UMS支持。 –