Domanda

Sto scrivendo un'applicazione .NET Windows Form che invierà un messaggio a una coda Websphere MQ e quindi eseguirà il polling di una coda diversa per una risposta. Se viene restituita una risposta, l'applicazione elaborerà parzialmente la risposta in tempo reale. Ma la risposta deve rimanere nella coda in modo che un processo batch giornaliero, che legge anche dalla coda di risposta, possa eseguire il resto dell'elaborazione.

Sono arrivato a leggere il messaggio. Quello che non sono riuscito a capire è come leggerlo senza rimuoverlo.

Ecco cosa ho finora. Sono un principiante MQ, quindi eventuali suggerimenti saranno apprezzati. E sentiti libero di rispondere in 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

NOTA: non ho verificato che il mio codice rimuova effettivamente il messaggio. Ma è così che ho capito che MQ funziona, e quello sembra essere ciò che sta accadendo. Per favore correggimi se questo non è il comportamento predefinito.

È stato utile?

Soluzione

Devi aprire la coda con l'opzione MQOO_BROWSE. Quindi alla tua prima lettura fai un GET usando l'opzione MQGMO_BROWSE_FIRST. Infine, i GET successivi dovrebbero utilizzare l'opzione MQGMO_BROWSE_NEXT.

Nota: MQOO è opzioni aperte MQ e MQGMO è MQ Ottieni opzioni messaggio.

Altri suggerimenti

Dovresti davvero farlo con code separate. L'elaborazione di Fine giornata dovrebbe avere una propria coda. Dopo aver elaborato la parte del messaggio, lo si invia alla coda EOD.

Con l'opzione Sfoglia dovrai tenere traccia di quali messaggi hai già elaborato da qualche parte.

Inoltre, è possibile impostare un timeout di attesa su GET. Quindi non è necessario " attendere 1 secondo prima di controllare la coda " ;. Come scritto in questo momento non è possibile raggiungere la condizione di no msg disponibile perché non hai impostato NOWAIT nelle opzioni di get message.

Per i posteri, ecco una versione (credo) molto migliorata del metodo basato sulle risposte di mamboking e 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

Mi rendo conto che sto arrivando a questa discussione un po 'tardi e probabilmente hai già codificato questa app. Nel caso in cui dovessi mai modificarlo o per chiunque abbia bisogno di fare qualcosa di simile, ho un paio di osservazioni.

Innanzitutto, se è possibile farlo con un QMgr v7 e un client WMQ v7, questa sarebbe la soluzione preferita. Nella v7, il supporto .Net è stato spostato da SupportPac a parte del prodotto di base. Vi sono nuove funzionalità considerevoli, alcune correzioni di errori e prestazioni migliori. Inoltre, su v7 puoi usare pub-sub ... che mi porta alla mia seconda osservazione.

Sulla base della descrizione del post originale, avrei fatto questo in Pub-Sub. L'app che mette il messaggio deve solo metterne uno e non ha nemmeno bisogno di sapere che sta mettendo in discussione un argomento. Puoi effettivamente mettere un alias su un argomento che lo fa sembrare una coda per il produttore del messaggio. Le app che consumano possono quindi iscriversi oppure è possibile effettuare due abbonamenti amministrativi in ??modo che i messaggi pubblicati passino a due code designate. Le tue app hanno quindi una coda dedicata e non sono previste modifiche alla codifica per il produttore e l'app batch, è solo una configurazione. Ovviamente l'app che guida le transazioni dovrebbe effettivamente consumare i messaggi piuttosto che sfogliarli.

I vantaggi qui sono diversi:

  • Man mano che la coda si riempie di messaggi, l'indicizzazione viene scaricata sul disco e al di sopra di una soglia verrà visualizzato un hit delle prestazioni che potrebbe essere significativo. Pertanto, l'attuale metodo non si adatta molto bene.
  • Con il metodo pub-sub puoi avere più istanze delle app in tempo reale o batch o entrambe, e queste possono trovarsi sullo stesso o su un altro QMgr. Il ridimensionamento è semplice.
  • Elimina la dipendenza tra le app in tempo reale e in batch che devono essere sullo stesso QMgr.
  • Amministrazione più trasparente. Se vedi accumularsi messaggi nella coda in tempo reale, sai di avere un problema.

Anche qui un paio di problemi completamente diversi. Uno di questi consiste nell'utilizzare l'opzione Fail if Quiescing. Lo scopo di questo è che quando QMgr viene chiuso in modo pulito questa opzione fa terminare la chiamata API con un codice di ritorno che indica che QMgr si sta spegnendo. Se non includi questa opzione, è possibile con due o più app connesse che QMgr non mai si spenga in modo pulito e debba essere forzato o che i suoi processi vengano interrotti con forza bruta. Di norma, utilizzare sempre Fail se Quiescing su tutte le chiamate API che lo supportano. Il motivo per cui esiste affatto è per le persone che hanno bisogno di transazioni XA ma per qualche motivo non possono usarlo. In questo scenario, CONNECT e la prima chiamata GET o PUT utilizzano Fail se Set di sospensione e le successive operazioni GET o PUT no. Questo fa sì che QMgr attenda il completamento dell'intero set di chiamate GET / PUT ma poi il successivo CONNECT o GET / PUT usa Fail se Quiescing, quindi QMgr ha la possibilità di chiudere se necessario.

L'altra osservazione qui è che qui non c'è Catch nel codice. Immagino che ce ne sia uno nel campo di applicazione più in alto nello stack di chiamate? È sempre consigliabile stampare il codice di ritorno WMQ da un'eccezione in modo da poter rintracciare la causa principale. In caso di impegni di consulenza, consiglio sempre ai clienti che la mancata stampa del codice di ritorno (o dell'eccezione collegata per il codice JMS / XMS) è uno showtopper che dovrebbe impedire la promozione di un'app alla produzione. È davvero così importante. Anche se hai un problema con il codice che chiama getMessage (), qualcuno che riutilizza lo snippet di codice di esempio qui potrebbe non rendersi conto che questo pezzo importante è mancante.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top