Test connection to the IBM MQ server every couple of minutes - c#

We are using the IBM.XMS 8.0.0.5 .NET library to connect to the IBM MQ server and create our listeners.
But sometimes the VPN tunnel goes in sleep mode (this happens if one of our servers restarts for example). To prevent this, it is necessary to keep the VPN tunnel 'awake' by sending a network packet through the tunnel.
I looked around but IBM MQ does not have any implementation to test the connection to the server. I need some kind of 'ping' which will keep the tunnel up. But pinging is not allowed, I think they reject ICMP echos.
I am planning to create an async Task which will test the connection regularly depending on a configured interval.
Any advice on this one please?
PS Sometimes the connection falls asleep as I mentioned above. And without knowing anything the system engineer restarts the service which sends a dispose to the IBM server, even a dispose message leads to the connection being back up. And all items on the queue start being consumed by us while the service is being stopped... I need to solve this but I don't have a clue how I can do this.
EDIT
Connection is made and consumers are set up as follows:
var factoryFactory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);
// Create WMQ Connection Factory.
var cf = factoryFactory.CreateConnectionFactory();
// Set the properties
cf.SetStringProperty(XMSC.WMQ_HOST_NAME, _parameters.IbmMqHost);
cf.SetIntProperty(XMSC.WMQ_PORT, _parameters.IbmMqPort);
cf.SetStringProperty(XMSC.WMQ_CHANNEL, _parameters.IbmMqChannel);
cf.SetIntProperty(XMSC.WMQ_CONNECTION_MODE, XMSC.WMQ_CM_CLIENT);
cf.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, _parameters.IbmMqQueueManager);
cf.SetStringProperty(XMSC.USERID, username);
cf.SetStringProperty(XMSC.PASSWORD, pw);
cf.SetIntProperty(XMSC.WMQ_CLIENT_RECONNECT_OPTIONS, XMSC.WMQ_CLIENT_RECONNECT);
// Create connection.
connection = cf.CreateConnection();
connection.ExceptionListener = ExceptionCallback;
session = connection.CreateSession(false, AcknowledgeMode.AutoAcknowledge);
destination = session.CreateQueue(queuename);
consumer = session.CreateConsumer(destination);
consumer.MessageListener = listener;
connection.Start();

Related

How to connect Remote RabbitMQ Server

I am going to build application (Asp.net C#) to connect RabbitMQ server which is in another country.
So my question is how to connect that server.
I already installed RabbitMQ Client from NuGet Packages.
Is that needed to run RabbitMQ service in my local machine ?
Need to install RabbitMQ Server in my local machine?
From Client some of the parameters i got like
UserName, Password, HostName, Certificate with private key.
I am curious to know which are the basic steps to connect that server from my localhost application.
Can someone provide blog to refer ?
I already tried with different steps but not able to connect.
string vCertSubjectName = "CN=DevRepo, OU=IT, O=OLX, L=KTM, S=Surrey, C=UK";
ConnectionFactory factory = new ConnectionFactory();
factory.AuthMechanisms = new AuthMechanismFactory[] { new ExternalMechanismFactory() };
factory.HostName = "195.168.0.15";
factory.Port = 5673;
factory.Ssl.Certs = getCertificate(vCertSubjectName);
factory.Ssl.ServerName = System.Net.Dns.GetHostName();
factory.Ssl.Enabled = true;
factory.Ssl.Version = SslProtocols.Tls12;
IConnection connection = factory.CreateConnection();
Error coming like connection.start was never received, likely due to a network timeout."
There are very good simple examples of how to write code to send and receive messages to/from RabbitMQ on their site.
Get those examples; set up a RabbitMQ server on your local network; build the examples and verify they work. Once you know how to send/receive to/from a known instance, you can change the connection properties in your send program to point it to the RabbitMQ instance elsewhere.
I would also suggest you do a ping to the IP address of the foreign RabbitMQ server to get an idea of actual transit times. That should give you some idea if the network timeout is a valid issue.
PS. You will need a valid login and password for the RabbitMQ server before it will accept any messages from you. When you build the example programs above as long as you are on the same physical machine where RabbitMQ is running, you can use the default login and password of guest/guest. By default this will NOT work from another machine due to default security configuration of RabbitMQ.

Close a WCF persistent connection

I have a problem with closing WCF persistent connection. I need not just to close an object, but close an established TCP connection.
What I have:
Many clients which can create a WCF connection like this:
var binding = new BasicHttpBinding
{
CloseTimeout = TimeSpan.FromMinutes(30),
ReceiveTimeout = TimeSpan.FromMinutes(30),
SendTimeout = TimeSpan.FromMinutes(30),
OpenTimeout = TimeSpan.FromMinutes(30)
};
var endpointAddress = new EndpointAddress(comboBoxPath.Text);
_factory = new ChannelFactory<IManagementService>(binding, endpointAddress);
_multimodeService = _factory.CreateChannel();
Load Balancer with 2 servers.
What I need is just recreate a WCF connection after removing one server from LB. Case: many clients have persistent connections to both servers via LB. I want to exclude one server from LB, update it and return it back but all clients must work with other server during update period. So when I exclude server from LB and start an update all clients working with the first server started to get errors. They try to recreate a WCF connection but they can't, because I can't close a persistent WCF connection and LB continue to sent requests to he first server. If I could fully close the connection and create a new one LB would send a request to the second server.
I tried to create a small test application to establish WCF connection and look at it by a small utility CurrPorts. I see the connection when I get data from a server but all my attempts to close the connection were unsuccessful. I tied
((ICommunicationObject)_multimodeService).Close();
((ICommunicationObject)_multimodeService).Abort();
((IClientChannel)_multimodeService).Close();
((IClientChannel)_multimodeService).Abort();
_factory.Close();
_factory.Abort();
but it just dispose object in code. So after closing connection by any of this actions I can't get data until I open a connection again but an established TCP connection is still alive and reused after a creation of new connection. It is removed only after closing the application.
So the question: is it possible to fully close a persistent connection including TCP connection?
Note: I know about caching in ChannelFactory and tried to set a property
ClientBase<IManagementService>.CacheSetting = CacheSetting.AlwaysOff;
at the start of application but it hasn't helped either.
My framework version is 4.6.2.

Create Queue Manager in a Declared Host

In C#, using IBM WebSphere MQ, I run:
var properties = new Hashtable();
properties.Add(MQC.HOST_NAME_PROPERTY, someHostName);
var queueManager = MQQueueManager(someQueueNameManager, properties);
I get an exception:
System.Exception: Channel and Connection MUST be specified
Obviously, it wants me to specify the channel. But I don't want to specify the channel. Is it important to specify it? I mean, When I run
var queueManager = MQQueueManager(someQueueNameManager);
It works and connects to the local MQ. How can I create an MQQueueManager object that connects to a queue manager in a different host without specifying any channel? If specifying a channel is necessary, please explain why that is the case.
You need a MQI Channel (Server Conn or Server Conn & Client Conn) to connect to a remote queue manager (ie a qmgr running on a remote host) over the network. The channel connects to the qmgr and puts/gets the messages for you. For a local qmgr, you can connect in bindings mode (and that's what you have done). This mode bypasses the network stack and connects to the qmgr using shared memory and semaphores.
This is one of the basic technical concept in IBM MQ. I suggest reading the MQ primer. It's small and covers all you need to know about MQ before using it.
http://www.redbooks.ibm.com/redpapers/pdfs/redp0021.pdf

It was not possible to connect to the redis server(s); to create a disconnected multiplexer, disable AbortOnConnectFail. SocketFailure on PING

I am trying to make a simple example of reading and writing from azure redis cache and I get this error
An exception of type 'StackExchange.Redis.RedisConnectionException' occurred in StackExchange.Redis.dll but was not handled in user code
Additional information: It was not possible to connect to the redis server(s); to create a disconnected multiplexer, disable AbortOnConnectFail. SocketFailure on PING
The code I am using is this, I changed dns and password
// Get Connection instance
ConnectionMultiplexer connection = ConnectionMultiplexer
.Connect("xx.redis.cache.windows.net,ssl=false,password=...");
// Get database
IDatabase databaseCache = connection.GetDatabase();
// Add items
databaseCache.StringSet("foo1", "1");
databaseCache.StringSet("foo2", "2");
// Add items with experation value
databaseCache.StringSet("foo3", "3", TimeSpan.FromMinutes(20));
Stopwatch sw = new Stopwatch();
sw.Start();
// Get item value
string foo1Value = databaseCache.StringGet("foo1");
sw.Stop();
Console.WriteLine("Elapsed={0}", sw.Elapsed);
return View();
Azure Redis Cache only enables the SSL endpoint by default. The most secure approach is to set "ssl=true" when calling ConnectionMultiplexer.Connect().
Alternatively, you can use the Azure Portal to enable the non-SSL endpoint on your Azure Redis Cache, but then your password and all data will be sent in clear text.
I had exact same exception and it turned out to be corporate firewall, which is blocking port 6379, 6380.
I copied my test console app in an environment outside company network and connection was successful.
So if Redis server is running on the internet and your network is behind a firewall make sure the ports are open.

TIBCO EMS Failover reconnect for C# (TIBCO.EMS.dll)

We have a TIBCO EMS solution that uses built-in server failover in a 2-4 server environment. If the TIBCO admins fail-over services from one EMS server to another, connections are supposed to be transfered to the new server automatically at the EMS service level. For our C# applications using the EMS service, this is not happening - our user connections are not being transfered to the new server after failover and we're not sure why.
Our application connection to EMS at startup only so if the TIBCO admins failover after users have started our application, they users need to restart the app in order to reconnect to the new server (our EMS connection uses a server string including all 4 production EMS servers - if the first attempt fails, it moves to the next server in the string and tries again).
I'm looking for an automated approach that will attempt to reconnect to EMS periodically if it detects that the connection is dead but I'm not sure how best to do that.
Any ideas? We are using TIBCO.EMS.dll version 4.4.2 and .Net 2.x (SmartClient app)
Any help would be appreciated.
First off, yes, I am answering my own question. Its important to note, however, that without ajmastrean, I would be nowhere. thank you so much!
ONE:
ConnectionFactory.SetReconnAttemptCount, SetReconnAttemptDelay, SetReconnAttemptTimeout should be set appropriately. I think the default values re-try too quickly (on the order of 1/2 second between retries). Our EMS servers can take a long time to failover because of network storage, etc - so 5 retries at 1/2s intervals is nowhere near long enough.
TWO:
I believe its important to enable the client-server and server-client heartbeats. Wasn't able to verify but without those in place, the client might not get the notification that the server is offline or switching in failover mode. This, of course, is a server side setting for EMS.
THREE:
you can watch for failover event by setting Tibems.SetExceptionOnFTSwitch(true); and then wiring up a exception event handler. When in a single-server environment, you will see a "Connection has been terminated" message. However, if you are in a fault-tolerant multi-server environment, you will see this: "Connection has performed fault-tolerant switch to ". You don't strictly need this notification, but it can be useful (especially in testing).
FOUR:
Apparently not clear in the EMS documentation, connection reconnect will NOT work in a single-server environment. You need to be in a multi-server, fault tolerant environment. There is a trick, however. You can put the same server in the connection list twice - strange I know, but it works and it enables the built-in reconnect logic to work.
some code:
private void initEMS()
{
Tibems.SetExceptionOnFTSwitch(true);
_ConnectionFactory = new TIBCO.EMS.TopicConnectionFactory(<server>);
_ConnectionFactory.SetReconnAttemptCount(30); // 30retries
_ConnectionFactory.SetReconnAttemptDelay(120000); // 2minutes
_ConnectionFactory.SetReconnAttemptTimeout(2000); // 2seconds
_Connection = _ConnectionFactory.CreateTopicConnectionM(<username>, <password>);
_Connection.ExceptionHandler += new EMSExceptionHandler(_Connection_ExceptionHandler);
}
private void _Connection_ExceptionHandler(object sender, EMSExceptionEventArgs args)
{
EMSException e = args.Exception;
// args.Exception = "Connection has been terminated" -- single server failure
// args.Exception = "Connection has performed fault-tolerant switch to <server url>" -- fault-tolerant multi-server
MessageBox.Show(e.ToString());
}
This post should sum up my current comments and explain my approach in more detail...
The TIBCO 'ConnectionFactory' and 'Connection' types are heavyweight, thread-safe types. TIBCO suggests that you maintain the use of one ConnectionFactory (per server configured factory) and one Connection per factory.
The server also appears to be responsible for in-place 'Connection' failover and re-connection, so let's confirm it's doing its job and then lean on that feature.
Creating a client side solution is going to be slightly more involved than fixing a server or client setup problem. All sessions you have created from a failed connection need to be re-created (not to mention producers, consumers, and destinations). There are no "reconnect" or "refresh" methods on either type. The sessions do not maintain a reference to their parent connection either.
You will have to manage a lookup of connection/session objects and go nuts re-initializing everyone! or implement some sort of session failure event handler that can get the new connection and reconnect them.
So, for now, let's dig in and see if the client is setup to receive failover notification (tib ems users guide pg 292). And make sure the raised exception is caught, contains the failover URL, and is being handled properly.
Client applications may receive notification of a failover by setting the tibco.tibjms.ft.switch.exception system property
Perhaps the library needs that to work?

Categories

Resources