首页 > 解决方案 > Visual Basic Web API 使用 mq 系列消息传递,但从不释放连接

问题描述

我正在研究一个遗留系统,并负责修改使用 mq 系列(现在称为 IBM websphere)从大型机系统发送和接收数据的 Visual Basic API。我的网络管理员通知我,他看到来自 API 的 97 个连接。在队列管理器级别,最大通道设置为 100。他说这很好,但问题是 API 建立了客户端通道连接但从未释放它。我假设必须有一个 close() 操作,一旦我从队列中检索响应,我就可以执行该操作,但我不知道语法是什么。这是我执行以发送和接收数据的代码:

    Dim passedmqRequest = mqRequest
    Dim Session_mq_put_array As Object
    Dim Session_mq_get_array As Object
    Dim Session_MqResponse As String = ""
    Dim Session_error_code As String = ""
    Dim Session_plan_id As String = Mid(passedmqRequest, 15, 4)

    Dim ipAddress As String = "xxx.xxx.xxx.xxx"

    Dim mq_get_error As String = "N"
    Dim mq_put_array(2) As String
    Dim mq_get_array(2) As String
    Dim Response_queue As String = ""
    Dim Response_queue_mgt As String = ""

    ' send messages to TOSSMQT1
    Response_queue = "ARI.GW1TEST.RESPONSES"
    Response_queue_mgt = "ARIT"
    mq_put_array(0) = "ARI.TEST.QUEUE"
    Response_queue = "ARI.TEST.RESPONSES"
    mq_put_array(1) = "VRU4300b"
    mq_put_array(2) = "SVRCONN//" & ipAddress & "(1414)" '* internal
    mq_put_array(2) = "SVRCONN//" & ipAddress & "(1414)" '* internal
    Session_mq_put_array = mq_put_array

    mq_get_array(0) = "ARI.TEST.HOST.RESPONSES"
    mq_get_array(1) = "VRU4300b"
    mq_get_array(2) = "SVRCONN//" & ipAddress & "(1414)" '* internal
    mq_get_array(2) = "SVRCONN//" & ipAddress & "(1414)" '* internal
    Session_mq_get_array = mq_get_array

    Dim CmdArgs() As String
    CmdArgs = Session_mq_put_array

    Dim CmdResponse() As String
    CmdResponse = Session_mq_get_array

    Dim mqQMgr As MQQueueManager            '* MQQueueManager instance 
    Dim mqQueue As MQQueue                  '* MQQueue instance 
    Dim responseQueue As MQQueue

    Dim mqMsg As MQMessage                  '* MQMessage instance 
    Dim responseMSG As MQMessage
    Dim mqPutMsgOpts As MQPutMessageOptions '* MQPutMessageOptions instance 
    Dim queueName As String                 '* Name of queue to use 
    Dim responsequeueName As String         '* Name of response queue to use 
    Dim message As String                   '* Message buffer 

    Dim mqError As String = ""

    queueName = CmdArgs.GetValue(0)
    responsequeueName = CmdResponse(0)

    '* 
    '* Try to create an MQQueueManager instance 
    '* 
    Dim channelDefinition As String = CmdArgs.GetValue(2)
    Dim channelName As String = ""
    Dim transportType As String = ""
    Dim connectionName As String = ""
    Dim separator As Char() = "/"
    Dim parts As String()
    Try
        '* queue name, queue manager name, channel definition all provided 
        '* Break down the channel definition, 
        '* which is of the form "channel-name/transport-type/connection-name". 
        channelDefinition = CmdArgs.GetValue(2)
        parts = channelDefinition.Split(separator)
        If (parts.Length > 0) Then
            channelName = parts(0)
        End If
        If (parts.Length > 1) Then
            transportType = parts(1)
        End If
        If (parts.Length > 2) Then
            connectionName = parts(2)
        End If
        mqQMgr = New MQQueueManager(CmdArgs.GetValue(1), channelName, connectionName)
        Try
            mqQueue = mqQMgr.AccessQueue(queueName, MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING)     '* open queue for output but not if MQM stopping 
            message = passedmqRequest
            '* put the next message to the queue 
            mqMsg = New MQMessage()
            mqMsg.WriteString(message)
            mqMsg.Format = MQC.MQFMT_STRING
            mqPutMsgOpts = New MQPutMessageOptions()
            mqMsg.ReplyToQueueName = Response_queue
            mqMsg.ReplyToQueueManagerName = Response_queue_mgt
            Try
                mqQueue.Put(mqMsg, mqPutMsgOpts)
                responseQueue = mqQMgr.AccessQueue(mq_get_array(0), MQC.MQOO_INPUT_SHARED + MQC.MQOO_FAIL_IF_QUIESCING)
                Dim MQGetMessageOptions As New MQGetMessageOptions()
                MQGetMessageOptions.Options = IBM.WMQ.MQC.MQGMO_WAIT + IBM.WMQ.MQC.MQGMO_FAIL_IF_QUIESCING + IBM.WMQ.MQC.MQGMO_CONVERT
                MQGetMessageOptions.WaitInterval = 20000
                MQGetMessageOptions.MatchOptions = MQC.MQMO_MATCH_MSG_ID

                responseMSG = New MQMessage
                responseMSG.MessageId = mqMsg.MessageId
                Try
                    responseQueue.Get(responseMSG, MQGetMessageOptions)
                    Session_MqResponse = responseMSG.ReadString(responseMSG.DataLength)
                    Session_error_code = "0"
'
'  at this point a response has been received and I should close
'  the client channel connection
'
                Catch mqe As MQException
                    '* report the error 
                    Session_MqResponse = "MQQueue::get ended with " & mqe.Message & "<br/>"
                    mq_get_error = "Y"
                    Session_error_code = "1"
                End Try
            Catch mqe As MQException
                '* report the error 
                Session_MqResponse = "MQQueue::Put ended with " & mqe.Message & "<br/>"
                Session_error_code = "2"
            End Try
        Catch mqe As MQException
            '* stop if failed 
            Session_MqResponse = "MQQueueManager::AccessQueue ended with error message = " & mqe.Message & "<br/>"
            Session_MqResponse = Session_MqResponse & "create of MQQueueManager ended with error reason = " & mqe.Reason & "<br/>"
            Session_error_code = "3"
        End Try
    Catch mqe As MQException
        '* stop if failed 
        Session_MqResponse = "create of MQQueueManager ended with error message = " & mqe.Message & "<br/>"
        Session_MqResponse = Session_MqResponse & "create of MQQueueManager ended with error reason = " & mqe.Reason & "<br/>"
        Session_error_code = "4"
    End Try

标签: vb.netibm-mq

解决方案


浏览您的代码:

mqQMgr = New MQQueueManager(...)

这将创建一个 MQQueueManager 对象,但也作为客户端连接连接到目标队列管理器 - 这将是网络管理员正在谈论的连接

mqQueue = mqQMgr.AccessQueue(queueName, MQC.MQOO_OUTPUT, ...)

这会在目标队列管理器上打开一个队列以进行输出

responseQueue = mqQMgr.AccessQueue(mq_get_array(0), MQC.MQOO_INPUT_SHARED, ...)

这会在目标队列管理器上打开一个队列以供输入。

此时,您在目标队列管理器上打开了 2 个队列和一个连接。如果您只是进入其他代码,那么您在服务器上持有资源。我的理解是,当对象超出范围时,它们会被销毁,但我可能对这种语言是错误的(不实践!)。

要显式释放资源,您只需关闭 qmgr 连接(因为它持有的任何队列都将被释放)并进行适当的错误检查:

mqQMgr.Disconnect()

如果您真的想显式清理队列然后清理队列管理器,您可以在断开连接之前执行以下操作(使用适当的错误检查):

mqQueue.Close()
responseQueue.Close()

推荐阅读