0

我有一个与MQ Queue transaction not rolling back in a 2 phase transaction 中描述的情况类似的问题。我有一个 .NET 客户端,它在一个事务中执行以下操作:

  1. 将一条记录写入第一个数据库。
  2. 将一条消息放入 IBM Websphere 8.0 MQ 系列队列。
  3. 使用 WS-AT 调用 Web 服务,如https://developers.redhat.com/quickstarts/eap/wsat-simple中所述。
  4. 将一条记录写入第二个数据库。

当 Web 服务回滚时,两个数据库回滚,但 IBM MQ Series 队列不回滚。当一个数据库出现故障时,IBM MQ Series 队列会回滚。

RestaurantTransactionPOC 方法在继承自 System.EnterpriseServices.ServicedComponent 的类中运行,也就是说,它在 COM+ 下运行。

下面是 RestaurantTransactionPOC 的代码:

Public Function RestaurantTransactionPOC(
    uri As String, queueManager As String, queueName As String, textToWrite As String,
    Optional failOnlRecvRep As Boolean = False,
    Optional failGtsRecvRep As Boolean = False,
    Optional failWSATService As Boolean = False,
    Optional failMQSeries As Boolean = False) As String
    Try
        Dim result = ""
        Dim msgId = GetMsgId()
        Try
            AddOnlRecvRep(msgId, failOnlRecvRep)
        Catch ex As Exception
            Debug.WriteLine(ex.ToString)
            result &= ex.ToString & vbCrLf
        End Try
        Try
            AddQueue(queueManager, queueName, msgId, failMQSeries)
        Catch ex As Exception
            Debug.WriteLine(ex.ToString)
            result &= ex.ToString & vbCrLf
        End Try
        Try
            ServicePointManager.SecurityProtocol = CType(SecurityProtocolType.Tls Or 768 Or 3072, SecurityProtocolType)
            Dim client = CreateChannel(Of RestaurantServiceATChannel)(uri)
            client.makeBooking()
        Catch ex As Exception
            Debug.WriteLine(ex.ToString)
            result &= ex.ToString & vbCrLf
        End Try
        Try
            AddGtsRecvRep(msgId, failGtsRecvRep)
        Catch ex As Exception
            Debug.WriteLine(ex.ToString)
            result &= ex.ToString
        End Try
        ContextUtil.SetComplete()
        Return result
    Catch ex As Exception
        ContextUtil.SetAbort()
        Throw
    End Try
End Function

Public Function CreateChannel(Of T)(uri As String) As T
            binding = New CustomBinding(
                New BindingElement() {
                    New TransactionFlowBindingElement(TransactionProtocol.WSAtomicTransaction11),
                    New TextMessageEncodingBindingElement() With {.MessageVersion = MessageVersion.Soap12},
                    New HttpsTransportBindingElement()})
    binding.SendTimeout = New TimeSpan(0, 0, 30)
    Dim endpoint As New EndpointAddress(uri)
    Dim channelFactory = New ChannelFactory(Of T)(binding, endpoint)
                Dim behavior = CType(channelFactory.Endpoint.Behaviors(1), ClientCredentials)
                behavior.ClientCertificate.SetCertificate(
                    StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint,
                    "5f 82 82 e3 e9 20 fd ac 27 f5 cc 60 8a f5 8e 55 39 38 a0 30")
    Return channelFactory.CreateChannel()
End Function

当 WS-AT makeBooking 服务回滚时,为什么 IBM MQ Series 队列不回滚?

4

2 回答 2

0

乔·齐策尔伯格是对的。一旦调用 AddQueue(调用 IBM.WMQ.MQQueue.Put),当前深度(由 IBM.WMQ.MQQueue.CurrentDepth 给出)就增加 1。但从队列中获取消息(由 IBM.WMQ. MQQueue.Get) 导致 MQRC_NO_MSG_AVAILABLE 异常。通过实验,我发现根据不同的情况,行为如下:

If ContextUtil.SetComplete is called, then
  If the transaction is committed, then
    CurrentDepth remains incremented. 
    The message is available for retrieval.
  Else (transaction is aborted, because Db or WS-AT voted abort)
    CurrentDepth remains incremented for 3 minutes, regardless of whether IBM.WMQ.MQQueue.Get is called in the meantime. Afther the 3 minutes, CurrentDepth returns to its original value (is decremented).
    The message is not available for retrieval.
  End If
Else (ContextUtil.SetAbort method is called)
  (transaction is aborted)
  CurrentDepth returns to original value (is decremented).
  The message is not available for retrieval.
End If
于 2022-01-31T14:17:40.070 回答
0

如果我没记错的话,在某些情况下,在进行读取尝试之前,MQ 不会从队列中删除消息,此时,如果消息没有正确提交,它将被撤回而不是传递给阅读器。可能想看看发送和接收队列管理器以及队列和阅读器的那些选项。

于 2022-01-31T04:40:26.390 回答