2014-04-28 2 views
1

일부 장기 실행 가져 오기 프로세스를 수행하기 위해 JMS를 사용하고 있지만 일부 중복 메시지 문제가 발생하여이를 잘 이해하지 못합니다.JMS가 메시지를 두 번 배달하는 이유는 무엇입니까?

흐름은 다음과 같습니다. 일부 backing bean 코드는 Message Bean에 메시지를 보냅니다. 메시지 Bean은이 메시지를 수신하여 써드 파티 서비스를 폴링 한 다음 가져올 새 데이터가 있으면이 행을 데이터베이스로 커밋합니다. 문제는 가져 오기 프로세스가 약 60 초 정도 걸리는 인스턴스에서 JMS가 내 메시지를 두 번 보내고 있다는 것입니다. 가져올 새 행이없고 프로세스에 30 초 정도 걸리면 메시지는 한 번만 전송됩니다.

메시지 인식의 승인과 관련이 있다고 생각하여 자동 승인이 작동하지 않았기 때문에 내가 한 첫 번째 작업은 QueueSession을 Session.CLIENT_ACKNOWLEDGE로 설정하고 msg.acknowledge()를 내 onMessage 메소드. 슬프게도 메시지는 여전히 두 번 전송되었습니다.

오류 코드 또는 예외가 발생하지 않습니다.

다음은 코드입니다. 지금은 가져 오기 메시지 콩

@Override 
public void onMessage(Message msg) { 
    try { 
      // create an ADF Application Module 
      // poll a third party for some data 
      // copy these rows (if new) and then 
      // commit via the ADF Application Module 
     } 
    catch (Exception e){ 
     // no errors are being thrown 
    } 
} 

에서

public MyBackingBean(){ 
    try { 
     InitialContext ctx = new InitialContext(); 
     qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY); 
     qcon = qconFactory.createQueueConnection(); 
     qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); 

     queue = (javax.jms.Queue) ctx.lookup(IMPORT_QUEUE); 
     qsender = qsession.createSender(queue); 
     qsender.setDeliveryMode(DeliveryMode.NON_PERSISTENT); 

     qcon.start(); 

    } catch (JMSException e) { 
     System.out.println(e); 
    } catch (NamingException e) { 
     System.out.println(e); 
    } 

public void startImport() { 
     try { 
      // send a JMS message for the long running job 
      MapMessage mapMessage = qsession.createMapMessage(); 
      mapMessage.setObjectProperty("ipAddress", "127.0.0.1"); 
      qsender.send(mapMessage); 
     } catch (JMSException e) { 
      e.printStackTrace(); 
     } catch (Throwable te) { 
      te.printStackTrace(); 
     } 
} 

백업의 콩에서

, 내가 메시지가 재전송 있는지 확인하여 중복을 무시하고있어 (msg.getJMSRedelivered()) 그리고 중복을 무시하고, 나는 반창고에 너무 만족하지 않는다.

아무에게도 이것에 대한 조언이 있습니까?

답변

1

무슨 일이 일어 났는지 확신 할 수는 없지만, AUTO_ACKNOWLEDGE를 사용하면 스레드가 onMessage() 호출에서 반환 될 때까지 실제로 응답이 발생하지 않습니다. 따라서 onMessage() 호출에서 60 초를 소비하는 경우 재 전달에 놀라지 않습니다. CLIENT_ACKNOWLEDGE를 사용하여 msg.acknowledge()를 호출하면 명시 적으로 메시지를 확인해야합니다. 그러나, 어느 시점에서 그렇게하고 있습니까? onMessage()에서 60 초를 소비 한 후에? 그렇다면 당신도 똑같은 행동을 할 것입니다. onMessage() 호출을 입력하자마자 msg.acknowledge()를 호출 할 수 있지만 나중에 onMessage() 메서드의 무언가가 충돌 할 경우 메시지가 다시 전달되지 않음을 알 수 있습니다. 어쨌든 지속적인 전달을 사용하지 않는 것 같아서 걱정하지 않으셔도됩니다.

다음은 좋은 참고 자료입니다.

http://www2.sys-con.com/itsg/virtualcd/Java/archives/0604/chappell/index.html#s1

관련 문제