2009-06-24 4 views
7

저는 Websphere MQ 대기열에 메시지를 게시 한 다음 응답을 위해 다른 대기열을 폴링 할 .NET Windows Forms 애플리케이션을 작성 중입니다. 응답이 리턴되면 어플리케이션은 부분적으로 실시간으로 응답을 처리합니다. 그러나 응답은 대기열에 있어야하므로 응답 큐에서 읽는 일일 일괄 처리 작업이 나머지 처리 작업을 수행 할 수 있습니다.Websphere MQ 메시지를 제거하지 않고 찾아 보는 방법은 무엇입니까?

나는 메시지를 읽은 상태 다. 내가 알아낼 수 없었던 것은 제거하지 않고 그것을 읽는 방법입니다.

내가 지금까지 가지고있는 것이있다. 나는 MQ 초보자 다. 그래서 어떤 제안이라도 인정 될 것이다. 그리고 C#에서 응답 해주십시오.

Public Function GetMessage(ByVal msgID As String) As MQMessage 
    Dim q = ConnectToResponseQueue() 
    Dim msg As New MQMessage() 
    Dim getOpts As New MQGetMessageOptions() 
    Dim runThru = Now.AddMilliseconds(CInt(ConfigurationManager.AppSettings("responseTimeoutMS"))) 
    System.Threading.Thread.Sleep(1000) 'Wait for one second before checking for the first response' 
    While True 
     Try 
      q.Get(msg, getOpts) 
      Return msg 
     Catch ex As MQException When ex.Reason = MQC.MQRC_NO_MSG_AVAILABLE 
      If Now > runThru Then Throw ex 
      System.Threading.Thread.Sleep(3000) 
     Finally 
      q.Close() 
     End Try 
    End While 
    Return Nothing 'Should never reach here' 
End Function 

참고 : 내 코드는 실제로 메시지를 제거하는 것을 확인하지 않았습니다. 그러나 그것이 MQ가 작동하는 것을 이해하는 방법이며, 그 일은 일어나는 것처럼 보입니다. 그것이 기본 동작이 아니라면 나를 바로 잡으십시오.

+0

+1 - 나 자신을 위해 알아 내려고하기 전에이 질문을 발견했으면 좋겠습니다. –

답변

11

MQOO_BROWSE 옵션을 사용하여 큐를 열어야합니다. 그런 다음 첫 번째 읽기에서 MQGMO_BROWSE_FIRST 옵션을 사용하여 GET을 수행하십시오. 마지막으로, 이후의 GET은 MQGMO_BROWSE_NEXT 옵션을 사용해야합니다.

주 : MQOO는 MQ 열기 옵션이고 MQGMO는 MQ 메시지 옵션 가져 오기입니다.

+0

알았어요. 고마워. –

+0

화려한 대답. 오늘 내 베이컨을 구해 줬어. 고맙습니다. – duffymo

1

정말 별개의 대기열을 사용해야합니다. 일과 종료 처리에는 자체 대기열이 있어야합니다. 메시지의 일부를 처리 한 후에는 EOD 큐로 보냅니다.

찾아보기 옵션을 사용하면 어딘가에서 이미 처리 한 메시지를 추적해야합니다.

또한 GET에서 대기 시간 제한을 설정할 수 있습니다. 따라서 "대기열을 확인하기 전에 1 초 기다릴 필요가 없습니다." 지금 쓰여 있듯이 get message 옵션에 NOWAIT를 설정하지 않았기 때문에 no msg available 조건을 사용할 수 없습니다.

+0

+1 좋은 지적. 나는 내 게시물에서 내가 한 번에 하나의 요청과 응답을하고 있다고 언급하지 않았다. 응답의 상관 ID는 요청의 메시지 ID와 일치하므로 이미 처리 한 메시지를 추적하는 것이 문제가되지 않아야합니다. 대기 제한 시간까지는 그걸 보았지만 그걸로 무엇을해야할지 알지 못했습니다. 나는 당신의 제안에 기반한 좀 더 많은 연구를 해왔고 그 접근법을 사용하여 그 방법을 상당히 정리했다. 고마워요! –

1

후손을 위해 mamboking과 jmucchiello의 답변을 바탕으로 한이 방법의 개선 된 버전이 있습니다.

Public Function GetMessage(ByVal correlID As Byte()) As MQMessage 
    Dim waitInterval = CInt(ConfigurationManager.AppSettings("responseTimeoutMS")) 
    Dim q As MQQueue = Nothing 
    Try 
     Dim msg As New MQMessage() 
     Dim getOpts As New MQGetMessageOptions() 
     q = ConnectToResponseQueue() 
     msg.MessageId = MQC.MQMI_NONE 
     msg.CorrelationId = correlID 
     getOpts.MatchOptions = MQC.MQMO_MATCH_CORREL_ID 
     getOpts.WaitInterval = waitInterval 
     getOpts.Options = MQC.MQGMO_BROWSE_FIRST Or MQC.MQGMO_WAIT 
     q.Get(msg, getOpts) 
     Return msg 
    Finally 
     If q IsNot Nothing AndAlso q.IsOpen() Then q.Close() 
    End Try 
End Function 
1

나는이 토론에 약간 늦게 왔고 아마도 이미이 응용 프로그램을 코딩했다고 생각합니다. 이벤트를 수정할 필요가 있거나 비슷한 것을해야 할 필요가있는 다른 사람들을 위해, 나는 몇 가지 관찰을했습니다.

먼저 v7 QMgr 및 v7 WMQ 클라이언트에서이 작업을 수행 할 수 있으면이 방법이 가장 좋습니다. v7에서 .Net 지원은 SupportPac에서 기본 제품의 일부로 이동되었습니다. 상당한 새로운 기능, 버그 수정 및 향상된 성능이 있습니다. 또한, v7에서는 pub-sub를 사용할 수 있습니다 ... 두 번째 관찰을 유도합니다.

원본 게시물의 설명에 따르면, 나는 Pub-Sub에서이 작업을 수행했을 것입니다. 메시지를 넣는 응용 프로그램은 메시지를 넣는 것만 필요하며 주제가있는 것을 알 필요도 없습니다. 실제로 메시지 생성자에 대한 대기열처럼 보이게하는 별칭에 별칭을 지정할 수 있습니다. 그런 다음 소비하는 앱을 구독하거나 두 개의 관리 구독을 만들어 게시 된 메시지가 지정하는 두 개의 대기열로 이동할 수 있습니다. 그런 다음 앱마다 전용 큐가 있으며 제작자와 일괄 앱에 코딩 변경이 필요하지 않습니다. 단지 구성 일뿐입니다. 물론 트랜잭션을 구동하는 앱은 실제로 메시지를 탐색하지 않고 메시지를 소비해야합니다.여기

장점은 몇 가지 있습니다 : 큐가 메시지로 채워

  • 으로 인덱싱 디스크에 당신이 중요 할 수있는 성능 저하를 볼 수 있습니다 임계 값 이상으로 플러시됩니다. 따라서 현재 방법은 모든 것을 잘 확장하지 못합니다.
  • pub-sub 방법을 사용하면 실시간 또는 일괄 앱 또는 둘 다의 여러 인스턴스를 가질 수 있으며이 인스턴스는 동일하거나 다른 QMgr에있을 수 있습니다. 스케일 업은 쉽습니다.
  • 동일한 QMgr에 있어야하는 실시간 앱과 일괄 앱 간의 종속성을 제거합니다.
  • 보다 투명한 투여. 실시간 대기열에 메시지가 쌓이면 문제가 있음을 알 수 있습니다.

여기에도 완전히 다른 두 가지 문제가 있습니다. 이 중 하나는 일시 중지시 실패 옵션을 사용하는 것입니다. 이것의 목적은 QMgr이 완전히 종료 될 때이 옵션은 API 호출이 QMgr 종료 중임을 나타내는 리턴 코드로 끝나게합니다. 이 옵션을 포함하지 않으면 두 개 이상의 연결된 응용 프로그램에서 QMgr이 이 아닐 수 있습니다.은 완전히 종료되고 강제로 중지되거나 프로세스가 무차별 적으로 중지되어야합니다. 일반적으로 지원하는 모든 API 호출에 대해 일시 중지 인 경우 실패를 사용하십시오. 그것이 존재하는 이유는 XA 트랜잭션 성이 필요한 사람들을위한 것이지만 어떤 이유로 그것을 사용할 수 없기 때문입니다. 이 시나리오에서 CONNECT와 첫 번째 GET 또는 PUT 호출은 정지 세트 및 후속 GET 또는 PUT 조작이 실패한 경우 실패를 사용합니다. 이로 인해 QMgr은 전체 GET/PUT 호출 집합이 완료 될 때까지 대기하지만 다음 CONNECT 또는 GET/PUT은 quiescing 인 경우 Fail을 사용하므로 QMgr은 필요한 경우 종료 할 수 있습니다.

다른 관찰은 여기서 코드에 캐치가 없다는 것입니다. 호출 스택을 확장하는 범위가 있다고 추측합니까? 근본 원인을 추적 할 수 있도록 항상 예외에서 WMQ 반환 코드를 인쇄하는 것이 좋습니다. 컨설팅에 관해서는 항상 고객에게 리턴 코드 (또는 JMS/XMS 코드의 링크 된 예외)를 인쇄하지 못하는 것이 앱을 프로덕션으로 승격시키는 것을 막아야한다는 사실을 조언합니다. 정말 중요합니다. getMessage()를 호출하는 코드를 잡아도 여기 예제 코드 조각을 재사용하는 사람은이 중요한 부분이 누락되었음을 깨닫지 못할 수 있습니다.