如何获取Websphere MQ连接状态以及如何重置连接:
1.)从.net客户端,如何测试客户端是否连接到服务器(即可以发送和接收)是的,我可以在try块内发送消息并捕获随后的exception,但我希望更优雅的解决方案。
2)如何打开,关闭和重新打开连接? 在我尝试解决上面的问题1时,我发现如果我打开连接然后调用connection.Close()我无法从连接工厂获得另一个连接(请参阅下面的代码片段)。 我收到错误消息XMSCC0008
我使用的是非常标准的vanilla MQ配置。 以下是我的客户端连接方式:
ISession session = MQAccess.GetSession(MQAccess.Connection); IDestination destination = session.CreateTopic(SubTopicName); Consumer = MQAccess.GetConsumer(session, destination); Consumer.MessageListener = new MessageListener(HandleMQSubEvent); MQAccess.Connection.Start();
其中MQAccess是一个小实用程序类。
编辑了添加MQAccess代码的问题:
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 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)); } } } } } }
编辑:将MQAccess类重命名为MQClient。 根据T Rob建议将其设为实例类。 断开连接方法仍然与上面列出的错误消息崩溃
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 ConnectionError; private Action IncomingMessageHandler; public MQClient(string subTopicName, string pubTopicName, Action 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 }
问题出在这里 – > where MQAccess is a small utility class.
问题的第一部分询问如何判断连接是否处于活动状态。 WebSphere MQ的XMS类是非Java平台的JMS规范的实现。 它们非常密切地遵循JMS规范,并且JMS规范在连接或会话上没有等效于isConnected
因此XMS也没有。 但是,所有GET和PUT活动都应该在try / catch块中进行,以便捕获JMSexception。 (从中总是打印linkedException
,对吗?)当抛出JMSexception时,应用程序要么将其视为致命并死亡,要么关闭除连接工厂之外的所有JMS对象,等待几秒然后重新驱动连接顺序。
根据问题中的新信息更新:
感谢您发布MQAccess类。 这提供了相当深入的了解正在发生的事情,尽管仍然没有任何代码显示连接关闭和重新打开的位置,根据问题的第2部分。
但是,代码显示MQAccess
类在MQAccess
类实例时创建ICONNECTION connection
的私有实例,然后将其作为MQAccess.GetConnection
公开公开。 当前发布的MQAccess
类没有公共或私有类方法可以替换连接所持有的连接句柄,因此如果MQAccess.Connection.Close()
,那么MQAccess
类中的IConnection
对象实例将在保持无效之后永远存在连接句柄。 关闭连接后, MQAccess
实例实际上已经死亡。 您必须删除并重新实例化MQAccess
才能获得新连接。
MQAccess
类确实公开了连接工厂,因此理论上可以从类外部调用MQAccess.GetConnection
并获取有效的新IConnection
对象,即使在关闭原始对象之后也是如此。 但是,该实例将存在于MQAccess
类的范围之外,因此对MQAccess
任何后续调用MQAccess
将引用其已停止的实例变量connection
而不是在类外部创建的新连接实例。
如果需要关闭并重新创建连接,可以考虑从MQAccess
内部进行MQAccess
。 一种低技术方法可能是为连接编写MQAccess.Close()
方法,该方法将关闭现有连接,然后立即调用connection = GetConnection();
这样私有connection
变量始终保持有效的连接句柄。
如果这不能解决问题,请发布正在关闭的代码并重新创建连接。
顺便说一句,通过网络连接的非事务会话打开了丢失或复制任何JMS提供程序(包括WMQ)的消息的可能性。 这是你的意图吗? 我在这里解释了为什么这是另一篇SOpost。
添加T.Rob的评论。
问题1:
我希望您可以访问MQAccess
源代码。 如果是,则可以在MQAccess
中公开一个属性,指示连接是否处于活动状态。 如果您没有访问权限,则可能必须要求该类的作者添加此属性。 您可以执行以下操作来设置/重置属性。
1)在createConnection方法成功返回后设置属性。
2)为连接设置Exception监听器。
3)重置exception处理程序中的属性。 检查原因代码并重置属性,如果它是连接中断错误(XMSWMQ1107和链接的exception可以具有MQRC 2009)。
问题2
如果您能告诉我们您是如何closing
和reopening
连接的话会有所帮助。 我建议关闭连接是:
1)首先进行连接.Stop()。
2)删除所有消息监听器,基本上做一个consumer.MessageListener = null。
3)然后执行connection.Close()。
4)做一个连接= null
附加信息以下是我用来测试的样本。
private void OnException(Exception ex) { XMSException xmsex = (XMSException)ex; Console.WriteLine("Got exception"); // Check the error code. if (xmsex.ErrorCode == "XMSWMQ1107") { Console.WriteLine("This is a connection broken error"); stopProcessing = true; // This is a class member variable } }
在创建连接的方法中,设置exception侦听器。
// Create connection. connectionWMQ = cf.CreateConnection(); connectionWMQ.ExceptionListener = new ExceptionListener(OnException);
只要存在连接错误,就会调用exception监听器并将flag设置为true。
在不再需要对象时处置对象是一种很好的做法。 有父子关系,Consumer,Producer等是Session的孩子,而Session又是Connection的孩子。 因此处置的顺序可以是孩子优先和父母下一个。 但如果处置父母,孩子也会自动处理。
- 检查阻止集合中的重复项
- 使用json.net大小限制序列化数据?
- 将字符串转换为.net中的日期
- 在构造ExtendedPropertyDefinition时,我应该使用GUID还是DefaultExtendedPropertySet.PublicStrings?
- 无法在Elastic Beanstalk部署上加载文件或程序集Magick.Net
- 套接字上的Protobuf-net序列化。 没有无参数构造函数发现ProtoException
- WPF本地化:带StringFormat的DynamicResource?
- 为什么我不能在WebForm中声明UserControl的子元素(属性)?
- 我可以将WCF DataContract添加到复杂类型吗?