我如何获得WebSphere MQ的连接状态以及如何重新连接: [英] How do I get Websphere MQ connection status and how do I reset the connection:

查看:1206
本文介绍了我如何获得WebSphere MQ的连接状态以及如何重新连接:的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

1)从.NET客户端,我怎么测试,如果客户端连接到服务器(即可以发送和接收)是的,我可以把一个消息的try块内,赶上随后的例外,但我中号希望有一个更好的解决方案。

2)如何打开,关闭,并重新打开连接?在我试图解决的问题1上面我发现,如果我打开一个连接,然后调用connection.close()时,我无法获得连接工厂的另一个连接(见下文code片段)。我收到错误消息XMSCC0008

我使用的是非常标准的香草MQ配置。下面是我的客户端连接:

 的ISession会话= MQAccess.GetSession(MQAccess.Connection);
IDestination目的地= session.CreateTopic(SubTopicName);
消费= MQAccess.GetConsumer(会话,目的地);
Consumer.MessageListener =新的MessageListener(HandleMQSubEvent);
MQAccess.Connection.Start();
 

在这里MQAccess是一个小工具类。

编辑了问题补充MQAccess code:

 公共静态类MQAccess
{
    公共静态只读MQConfigurationSectionHandler ConfigSettings;
    公共静态只读IConnectionFactory连接工厂;

    私人静态只读IConnection连接;
    公共静态IConnection连接
    {
        {返回连接; }
    }

    静态MQAccess()
    {
        ConfigSettings =(MQConfigurationSectionHandler)
            ConfigurationManager.GetSection(MQ-配置);

        XMSFactoryFactory厂= XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);
        连接工厂= factory.CreateConnectionFactory();
        ConnectionFactory.SetStringProperty(XMSC.WMQ_HOST_NAME,ConfigSettings.Hostname);
        ConnectionFactory.SetIntProperty(XMSC.WMQ_PORT,ConfigSettings.Port);
        ConnectionFactory.SetStringProperty(XMSC.WMQ_CHANNEL,ConfigSettings.Channel);

        如果(ConfigSettings.QueueManager ==的String.Empty)
        {
            ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER,);
        }
        其他
        {
            ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER,ConfigSettings.QueueManager);
        }

        连接=的getConnection();
    }

    公共静态IConnection的getConnection()
    {
        返回ConnectionFactory.CreateConnection();
    }

    公共静态的ISession的getSession(IConnection连接)
    {
        返回connection.CreateSession(假,AcknowledgeMode.AutoAcknowledge);
    }

    公共静态IMessageProducer GetProducer(ISession的会议上,IDestination目的地)
    {
        返回session.CreateProducer(目标);
    }

    公共静态IMessageConsumer GetConsumer(ISession的会议上,IDestination目的地)
    {
        返回session.CreateConsumer(目标);
    }

    公共静态无效MQPub(字符串TopicURI,字符串消息)
    {
        使用(VAR会话=的getSession(连接))
        {
            使用(VAR的目标= session.CreateTopic(TopicURI))
            {
                使用(VAR制片= GetProducer(会话,目的地))
                {
                    producer.Send(session.CreateTextMessage(消息));
                }
            }
        }
    }

    公共静态无效MQPub(字符串TopicURI,IEnumerable的<字符串>消息)
    {
        使用(VAR会话=的getSession(连接))
        {
            使用(VAR的目标= session.CreateTopic(TopicURI))
            {
                使用(VAR制片= GetProducer(会话,目的地))
                {
                    的foreach(在邮件VAR消息)
                    {
                        producer.Send(session.CreateTextMessage(消息));
                    }
                }
            }
        }
    }
}
 

编辑:重命名MQAccess类MQClient。使它元T罗布建议类的实例。 Disconnect方法仍与上述

中列出的错误封邮件崩溃

 公共类MQClient:IDisposable的
{
    公共MQConfigurationSectionHandler ConfigSettings {获得;私定; }
    公共IConnectionFactory连接工厂{获得;私定; }

    公共IConnection连接{获得;私定; }

    公共IMessageConsumer消费{获得;私定; }
    公共IMessageProducer生产者{获得;私定; }
    //保存会话作为处理和领域未来订阅功能
    私人ISession的ProducerSession;
    私人ISession的ConsumerSession;
    公共字符串SubTopicName {获得;私定; }
    公共字符串PubTopicName {获得;私定; }
    公共BOOL IsConnected {获得;私定; }
    公共事件动作<异常>连接错误;
    民营动作<即时聊天> IncomingMessageHandler;

    公共MQClient(字符串subTopicName,串pubTopicName,动作<即时聊天> incomingMessageHandler)
    {
        //不要把连接逻辑构造。如果我们失去了联系,我们可能需要重新连接。
        SubTopicName = subTopicName;
        PubTopicName = pubTopicName;
        IncomingMessageHandler = incomingMessageHandler;
    }

    公共字符串连接()
    {
        IsConnected = FALSE;
        字符串ERRORMSG =的String.Empty;

        ConfigSettings =(MQConfigurationSectionHandler)
                ConfigurationManager.GetSection(MQ-配置);

        XMSFactoryFactory厂= XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);
        连接工厂= factory.CreateConnectionFactory();
        ConnectionFactory.SetStringProperty(XMSC.WMQ_HOST_NAME,ConfigSettings.Hostname);
        ConnectionFactory.SetIntProperty(XMSC.WMQ_PORT,ConfigSettings.Port);
        ConnectionFactory.SetStringProperty(XMSC.WMQ_CHANNEL,ConfigSettings.Channel);

        如果(ConfigSettings.QueueManager ==的String.Empty)
            ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER,);
        其他
            ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER,ConfigSettings.QueueManager);

        连接= ConnectionFactory.CreateConnection();


        如果(!string.IsNullOrEmpty(PubTopicName))
        {
            ProducerSession = Connection.CreateSession(假,AcknowledgeMode.AutoAcknowledge);
            制片= ProducerSession.CreateProducer(ProducerSession.CreateTopic(PubTopicName));
        }

        如果(string.IsNullOrEmpty(SubTopicName)及!&安培;!IncomingMessageHandler = NULL)
        {
            ConsumerSession = Connection.CreateSession(假,AcknowledgeMode.AutoAcknowledge);
            消费者= ConsumerSession.CreateConsumer(ConsumerSession.CreateTopic(SubTopicName));
            Consumer.MessageListener =新的MessageListener(IncomingMessageHandler);
        }

        尝试
        {
            Connection.Start();
            Connection.ExceptionListener =新的ExceptionListener(ConnectionExceptionHandler);
            IsConnected = TRUE;
        }
        赶上(TypeInitializationException前)
        {
            ERRORMSG =试图连接到MQ一TypeInitializationException出错检查队列配置在App.config中的错误信息是:+ ex.Message;
        }
        赶上(IllegalStateException异常前)
        {
            ERRORMSG =试图连接到MQ一个IllegalStateException出错检查队列配置在App.config中的错误信息是:+ ex.Message;
        }

        返回ERRORMSG;
    }

    公共无效断开()
    {
        如果(监制!= NULL)
        {
            Producer.Close();
            Producer.Dispose();
            制片= NULL;
        }

        如果(ProducerSession!= NULL)
        {
            //调用退订这里如果认购耐用

            ProducerSession.Close();
            ProducerSession.Dispose();
            ProducerSession = NULL;
        }

        如果(连接!= NULL)
        {
            Connection.Stop();

            //如果(Connection.ExceptionListener!= NULL)
            // Connection.ExceptionListener = NULL;

            //每沙市............
            //如果(Consumer.MessageListener!= NULL)
            // Consumer.MessageListener = NULL;

            的Connection.close();
            Connection.Dispose();
            连接= NULL;
        }

        如果(消费者!= NULL)
        {

            如果(Consumer.MessageListener!= NULL)
                Consumer.MessageListener = NULL;

            Consumer.Close();
            Consumer.Dispose();
            消费= NULL;
        }


        如果(ConsumerSession!= NULL)
        {
            //调用退订这里如果认购耐用
            ConsumerSession.Close();
            ConsumerSession.Dispose();
            ConsumerSession = NULL;
        }

        IsConnected = FALSE;
    }


    公共无效的发布(字符串消息)
    {
        Producer.Send(ProducerSession.CreateTextMessage(消息));
    }


    公共无效的发布(字符串[]消息)
    {
        的foreach(在邮件string信息)
            发布(MSG);
    }

    公共无效ConnectionExceptionHandler(例外前)
    {
        断开(); // 清理

        如果(ConnectionError!= NULL)
            ConnectionError(前);
    }

    #地区IDisposable的成员
    私人BOOL处置;

    公共无效的Dispose()
    {
        处置(真);
        GC.Sup pressFinalize(本);
    }

    受保护的虚拟无效的Dispose(BOOL处置)
    {
        如果(!this.disposed)
        {
            如果(处置)
                断开();

            处置= TRUE;
        }
    }
    #endregion

}
 

解决方案

现在的问题是在这里 - > 其中MQAccess是一个小工具类

这个问题的第一部分询问如何辨别真假,如果连接处于活动状态。该XMS类的WebSphere MQ JMS规范的非Java平台上的实现。他们遵循JMS规范相当密切的JMS规范没有对连接或会话相当于一个方法 isConnected 因此同样没有XMS。然而,所有的GET和PUT活动应该在try / catch块中出现为了赶JMS异常。 (从您的总是的打印 linkedException ,对吧?)当一个JMS异常被抛出应用程序要么将其视为致命和死亡要不然关闭除连接工厂的所有JMS对象,等待几秒钟,然后再驱动连接顺序。

的基础上,在问题的新信息更新:
感谢张贴的MQAccess类。这提供了非常深入的看法发生了什么,虽然依然没有任何code表示将连接被关闭并重新打开按问题的一部分#2。

不过,code显示, MQAccess 类创建的 ICONNECTION连接私有的实例为类实例构造,然后公开公开为 MQAccess.GetConnection 。该 MQAccess 作为目前发布的类有一个会永远取代连接句柄持有连接任何公共或私有的类方法等等如果 MQAccess.Connection.Close()是不断呼吁,即在 IConnection 对象实例的 MQAccess 类将永远后举行无效连接句柄。一旦连接被​​关闭, MQAccess 的该实例是有效地死了。你不得不删除和再次 MQAccess 来获得一个新的连接。

MQAccess 类不公开揭露连接工厂,以便在理论上是可以调用 MQAccess.GetConnection 从类的外部并获得有效的新 IConnection 的对象,即使在关闭原来的一前一后。然而,该实例会存在于 MQAccess 类的范围之内,因此,任何后续调用 MQAccess 将参考其倒闭的实例变量连接而不是类之外创建新的连接实例。

如果您需要关闭并重新连接,你可以考虑管理,从 MQAccess 里面。低技术的方法可能是编写一个 MQAccess.Close()方法,这将关闭现有的连接,然后立即打电话连接=的getConnection的连接(); ,使私营连接变量总是持有有效的连接句柄

如果这样做不能解决该问题,请张贴正在关闭并重新创建连接code。

另外,非事务会话通过网络连接打开丢失或重复消息任何JMS提供者,包括WMQ的可能性。是这样的,你有什么打算?我已经解释了为什么这是一个其他SO发布<一个href="http://stackoverflow.com/questions/4741713/relationship-between-jms-connections-sessions-and-producers-consumers/4748080#4748080">here.

1.) From a .net client, how do I test if the client is connected to the server (i.e. can send and receive) Yes, I could send a message inside a try block and catch the ensuing exception but I'm hoping for a more elegant solution.

2) How do I open, close, and re-open connections? In my attempts to resolve question 1 above I discovered that if I open a connection then call connection.Close() I am not able to obtain another connection from the connection factory (see code fragment below). I receive error message XMSCC0008

I am using a very standard vanilla MQ configuration . Here is how my client connects:

ISession session = MQAccess.GetSession(MQAccess.Connection);
IDestination destination = session.CreateTopic(SubTopicName);
Consumer = MQAccess.GetConsumer(session, destination);
Consumer.MessageListener = new MessageListener(HandleMQSubEvent);
MQAccess.Connection.Start();

where MQAccess is a small utility class.

Edited the question to add MQAccess code:

public static class MQAccess
{
    public static readonly MQConfigurationSectionHandler ConfigSettings;
    public static readonly IConnectionFactory ConnectionFactory;

    private static readonly IConnection connection;
    public static IConnection Connection
    {
        get { return connection; }
    }

    static MQAccess()
    {
        ConfigSettings = (MQConfigurationSectionHandler)
            ConfigurationManager.GetSection("mq-configuration");

        XMSFactoryFactory factory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);
        ConnectionFactory = factory.CreateConnectionFactory();
        ConnectionFactory.SetStringProperty(XMSC.WMQ_HOST_NAME, ConfigSettings.Hostname);
        ConnectionFactory.SetIntProperty(XMSC.WMQ_PORT, ConfigSettings.Port);
        ConnectionFactory.SetStringProperty(XMSC.WMQ_CHANNEL, ConfigSettings.Channel);

        if (ConfigSettings.QueueManager == string.Empty)
        {
            ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, "");
        }
        else
        {
            ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, ConfigSettings.QueueManager);
        }

        connection = GetConnection();
    }

    public static IConnection GetConnection()
    {
        return ConnectionFactory.CreateConnection();
    }

    public static ISession GetSession(IConnection connection)
    {
        return connection.CreateSession(false, AcknowledgeMode.AutoAcknowledge);
    }

    public static IMessageProducer GetProducer(ISession session, IDestination destination)
    {
        return session.CreateProducer(destination);
    }

    public static IMessageConsumer GetConsumer(ISession session, IDestination destination)
    {
        return session.CreateConsumer(destination);
    }

    public static void MQPub(string TopicURI, string message)
    {
        using (var session = GetSession(Connection))
        {
            using (var destination = session.CreateTopic(TopicURI))
            {
                using (var producer = GetProducer(session, destination))
                {
                    producer.Send(session.CreateTextMessage(message));
                }
            }
        }
    }

    public static void MQPub(string TopicURI, IEnumerable<string> messages)
    {
        using (var session = GetSession(Connection))
        {
            using (var destination = session.CreateTopic(TopicURI))
            {
                using (var producer = GetProducer(session, destination))
                {
                    foreach (var message in messages)
                    {
                        producer.Send(session.CreateTextMessage(message));
                    }
                }
            }
        }
    }
}

Edit: Renamed MQAccess class to MQClient. Made it an instance class per T Rob suggestion. Disconnect method still crashes with error msgs listed above

public class MQClient : IDisposable
{
    public MQConfigurationSectionHandler ConfigSettings { get; private set; }
    public IConnectionFactory ConnectionFactory { get; private set; }

    public IConnection Connection { get; private set;  }

    public IMessageConsumer Consumer { get; private set; }
    public IMessageProducer Producer { get; private set; }
    // Save sessions as fields for disposing and future subscription functionality
    private ISession ProducerSession;
    private ISession ConsumerSession;
    public string SubTopicName { get; private set; }
    public string PubTopicName { get; private set; }
    public bool IsConnected { get; private set; }
    public event Action<Exception> ConnectionError;
    private Action<IMessage> IncomingMessageHandler;

    public MQClient(string subTopicName, string pubTopicName, Action<IMessage> incomingMessageHandler)
    {
        // Dont put connect logic in the constructor.  If we lose the connection we may need to connect again.
        SubTopicName = subTopicName;
        PubTopicName = pubTopicName;
        IncomingMessageHandler = incomingMessageHandler;
    }

    public string Connect()
    {
        IsConnected = false;
        string errorMsg = string.Empty;

        ConfigSettings = (MQConfigurationSectionHandler)
                ConfigurationManager.GetSection("mq-configuration");

        XMSFactoryFactory factory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);
        ConnectionFactory = factory.CreateConnectionFactory();
        ConnectionFactory.SetStringProperty(XMSC.WMQ_HOST_NAME, ConfigSettings.Hostname);
        ConnectionFactory.SetIntProperty(XMSC.WMQ_PORT, ConfigSettings.Port);
        ConnectionFactory.SetStringProperty(XMSC.WMQ_CHANNEL, ConfigSettings.Channel);

        if (ConfigSettings.QueueManager == string.Empty)
            ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, "");
        else
            ConnectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, ConfigSettings.QueueManager);

        Connection = ConnectionFactory.CreateConnection();


        if (!string.IsNullOrEmpty(PubTopicName))
        {
            ProducerSession = Connection.CreateSession(false, AcknowledgeMode.AutoAcknowledge);
            Producer = ProducerSession.CreateProducer(ProducerSession.CreateTopic(PubTopicName));
        }

        if (!string.IsNullOrEmpty(SubTopicName) && IncomingMessageHandler != null)
        {
            ConsumerSession = Connection.CreateSession(false, AcknowledgeMode.AutoAcknowledge);
            Consumer = ConsumerSession.CreateConsumer(ConsumerSession.CreateTopic(SubTopicName));
            Consumer.MessageListener = new MessageListener(IncomingMessageHandler);
        }

        try
        {
            Connection.Start();
            Connection.ExceptionListener = new ExceptionListener(ConnectionExceptionHandler);
            IsConnected = true;
        }
        catch (TypeInitializationException ex)
        {
            errorMsg = "A TypeInitializationException error occured while attempting to connect to MQ.  Check the Queue configuration in App.config. The error message is: " + ex.Message; 
        }
        catch (IllegalStateException ex)
        {
            errorMsg = "An IllegalStateException error occured while attempting to connect to MQ.  Check the Queue configuration in App.config. The error message is: " + ex.Message; 
        }

        return errorMsg;
    }

    public void Disconnect()
    {
        if (Producer != null)
        {
            Producer.Close();
            Producer.Dispose();
            Producer = null;
        }

        if (ProducerSession != null)
        {
            // Call Unsubscribe here if subscription is durable

            ProducerSession.Close();
            ProducerSession.Dispose();
            ProducerSession = null;
        }

        if (Connection != null)
        {
            Connection.Stop();

            //if (Connection.ExceptionListener != null)
            //    Connection.ExceptionListener = null;

            // Per Shashi............
            //if (Consumer.MessageListener != null)
            //    Consumer.MessageListener = null;

            Connection.Close();
            Connection.Dispose();
            Connection = null;
        }

        if (Consumer != null)
        {

            if (Consumer.MessageListener != null)
                Consumer.MessageListener = null;

            Consumer.Close();
            Consumer.Dispose();
            Consumer = null;
        }


        if (ConsumerSession != null)
        {
            // Call Unsubscribe here if subscription is durable
            ConsumerSession.Close();
            ConsumerSession.Dispose();
            ConsumerSession = null;
        }

        IsConnected = false;
    }


    public void Publish(string message)
    {
        Producer.Send(ProducerSession.CreateTextMessage(message));
    }


    public void Publish(string[] messages)
    {
        foreach (string msg in messages)
            Publish(msg);
    }

    public void ConnectionExceptionHandler(Exception ex)
    {
        Disconnect(); // Clean up

        if (ConnectionError != null)
            ConnectionError(ex);
    }

    #region IDisposable Members
    private bool disposed;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
                Disconnect();

            disposed = true;
        }
    }
    #endregion

}

解决方案

The problem is here --> where MQAccess is a small utility class.

The first part of the question asks how to tell if the connection is active. The XMS classes for WebSphere MQ are an implementation of the JMS specification for non-Java platforms. They follow the JMS spec fairly closely and the JMS spec does not have a method on the connection or session equivalent to isConnected therefore neither does XMS. However, all GET and PUT activity should occur within a try/catch block in order to catch the JMS exceptions. (From which you always print the linkedException, right?) When a JMS exception is thrown the app either treats it as fatal and dies or else it closes all JMS objects except for the Connection Factory, waits a few seconds and then re-drives the connection sequence.

UPDATE based on new info in the question:
Thanks for posting the MQAccess class. This provides considerable insight into what's happening, although there still isn't any code showing where the connection is closed and reopened as per Part #2 of the question.

However, the code shows that the MQAccess class creates a private instance of ICONNECTION connection as the class instance is constructed, which is then exposed publicly as MQAccess.GetConnection. The MQAccess class as currently posted has no public or private class method that would ever replace the connection handle held by connection so if MQAccess.Connection.Close() is ever called, that IConnection object instance within the MQAccess class will forever after hold an invalid connection handle. Once the connection is closed, that instance of MQAccess is effectively dead. You'd have to delete and reinstantiate MQAccess to get a new connection.

The MQAccess class does expose the connection factory publicly so in theory it would be possible to call MQAccess.GetConnection from outside the class and obtain a valid new IConnection object, even after closing the original one. However, that instance would exist outside the scope of the MQAccess class and thus any subsequent calls to MQAccess would refer to its defunct instance variable connection rather than the new connection instance created outside the class.

If you need to close and recreate connections, you might consider managing that from inside of MQAccess. A low-tech approach might be to write an MQAccess.Close() method for the connection which would close the existing connection then immediately call connection = GetConnection(); so that the private connection variable always holds a valid connection handle.

If this doesn't resolve the problem, please post the code that is closing and recreating the connections.

By the way, the non-transacted session over a network connection opens the possibility to lose or duplicate messages for any JMS provider, including WMQ. Was this what you intended? I've explained why this is in an other SO post here.

这篇关于我如何获得WebSphere MQ的连接状态以及如何重新连接:的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆