Auto-closing TIBCO EMS connections when no longer needed - c#

We're using TIBCO EMS from our ASP.NET 3.5 app for one interface to an external system, and it appears to be working just fine - except that the guys running the other side tells us we're racking up connections like crazy and never closing them....
What I'm doing is routing all TIBCO traffic through a single class with static member variables for both the TIBCO ConnectionFactory and the Connection itself, having been told that constructing them is pretty resource- and time-intensive:
private static ConnectionFactory Factory
{
get
{
if (HttpContext.Current.Application["EMSConnectionFactory"] == null)
{
ConnectionFactory connectionFactory = CreateTibcoFactory();
HttpContext.Current.Application["EMSConnectionFactory"] = connectionFactory;
}
return HttpContext.Current.Application["EMSConnectionFactory"] as ConnectionFactory;
}
}
private static Connection EMSConnection
{
get
{
if (HttpContext.Current.Application["EMSConnection"] == null)
{
Connection connection = Factory.CreateConnection(*username*, *password*);
connection.ExceptionHandler += new EMSExceptionHandler(TibcoConnectionExceptionHandler);
connection.Start();
HttpContext.Current.Application["EMSConnection"] = connection;
}
return HttpContext.Current.Application["EMSConnection"] as Connection;
}
}
Now my trouble is: where and how could I
tell the TIBCO connection to "auto-close" when no longer needed (like with the SqlConnection)
close the TIBCO connection on an error
close the TIBCO connection before our ASP.NET app finishes (or the user logs off)
I don't really seem to find much useful information on how to use TIBCO EMS from the C# / .NET world...... any takers?? Thanks!!

Firstly, I don't understand how you could be running out of connections. Since you're storing the connection in the application, you should only have a single connection for the entire IIS application.
That put aside, I would do the following:
When the connection is retrieved, create the connection as you do now;
After you've created the connection, spin up a background thread;
Set a DateTime to DateTime.Now;
Let the background check (e.g. every second or every 10 seconds) what the difference is between the date you've set and DateTime.Now. If that's longer than a specific timeout, kill the connection and set Application["EMSConnectionFactory"] to null;
When the background thread kills the connection, close the background thread;
Every time the connection gets requested, reset the DateTimetoDateTime.Now`.
This way, the connections should be closed automatically.
Note that you will have to introduce locking. You can use Application.Lock() and Application.Unlock() for this.
Concerning closing on an error: I see that you've attached an exception handler to the connection instance. Can't you close the connection with that?

Related

Understanding ASP.NET ConnectionPool and string security

I'm writing an application in ASP.NET, where I do frequent SQL Connections and by frequent I mean every 2 seconds. It's real time data application.
BD Engine is SQL SERVER 2008R2.
Each user connects to at least two different databases.
My problem is I still cant understand the connection pooling and how much of them connections I'll have after some queries.
I implemented the following methods:
private static string composeConnectionString(string connectTo)
{
StringBuilder sqlSB = new StringBuilder("Data Source=");
sqlSB.Append(dataSource);
sqlSB.Append(";Min Pool Size=");
sqlSB.Append(minPoolSize);
sqlSB.Append(";Max Pool Size=");
sqlSB.Append(maxPoolSize);
sqlSB.Append(";Connection Timeout=");
sqlSB.Append(connectionTimeout);
sqlSB.Append(";Initial Catalog=");
sqlSB.Append(connectTo);
sqlSB.Append(";Integrated Security=");
sqlSB.Append(integratesSecurity);
sqlSB.Append(";User Id=");
sqlSB.Append(userId);
sqlSB.Append(";Password=");
sqlSB.Append(password);
sqlSB.Append(";MultipleActiveResultSets=");
sqlSB.Append(multipleActiveResultSets);
return sqlSB.ToString();
}
public static SqlConnection getConnection(string connectTo)
{
SqlConnection connection = null;
string connectionString = composeConnectionString(connectTo);
try
{
connection = new SqlConnection(connectionString);
}
catch (Exception ex)
{
if (connection != null)
connection = null;
ExceptionLogger.LogException(ex, connectionString);
}
return connection;
}
At this point, I begin to question if new ConnectionPool is creater for every SQLConnection I seek?
How secure is the connection string?
Ask me for updates if something seem blurry.
Thank you all.
Depends of your configuration. If you configure your pool for at least one connection and a maximum of 3, when your first connection happens, if pooling is enabled, the connection will check for at least 1 and maximum of 3.
The pooler maintains ownership of the physical connection. It manages
connections by keeping alive a set of active connections for each
given connection configuration. Whenever a user calls Open on a
connection, the pooler looks for an available connection in the pool.
If a pooled connection is available, it returns it to the caller
instead of opening a new connection. When the application calls Close
on the connection, the pooler returns it to the pooled set of active
connections instead of closing it. Once the connection is returned to
the pool, it is ready to be reused on the next Open call.
You can read more here: https://msdn.microsoft.com/en-us/library/8xx3tyca%28v=vs.110%29.aspx
About the connection string, if you use user name and password as credentials, you have a security issue. You can use Windows Authentication to ensure your connection string does not have any sensitive data, or, if you're using IIS, you can store the connection string on it to protect your data.
Read more about connection string here: https://msdn.microsoft.com/pt-br/library/system.data.sqlclient.sqlconnection.connectionstring%28v=vs.110%29.aspx
And about protecting the connection string here: https://msdn.microsoft.com/en-us/library/89211k9b%28v=vs.110%29.aspx
Hope it helps.

Rabbit MQ - Recovery of connection/channel/consumer

I am creating a consumer that runs in an infinite loop to read messages from the queue. I am looking for advice/sample code on how to recover abd continue within my infinite loop even if there are network disruptions. The consumer has to stay running as it will be installed as a WindowsService.
1) Can someone please explain how to properly use these settings? What is the difference between them?
NetworkRecoveryInterval
AutomaticRecoveryEnabled
RequestedHeartbeat
2) Please see my current sample code for the consumer. I am using the .Net RabbitMQ Client v3.5.6.
How will the above settings do the "recovery" for me?
e.g. will consumer.Queue.Dequeue block until it is recovered?
That doesn't seem right
so...
Do I have to code for this manually? e.g. will consumer.Queue.Dequeue throw an exception for which I have to detect and manually re-create my connection, channel, and consumer? Or just the consumer, as "AutomaticRecovery" will recover the channel for me?
Does this mean I should move the consumer creation inside the while loop? what about the channel creation? and the connection creation?
3) Assuming I have to do some of this recovery code manually, are there event callbacks (and how do I register for them) to tell me that there are network problems?
Thanks!
public void StartConsumer(string queue)
{
using (IModel channel = this.Connection.CreateModel())
{
var consumer = new QueueingBasicConsumer(channel);
const bool noAck = false;
channel.BasicConsume(queue, noAck, consumer);
// do I need these conditions? or should I just do while(true)???
while (channel.IsOpen &&
Connection.IsOpen &&
consumer.IsRunning)
{
try
{
BasicDeliverEventArgs item;
if (consumer.Queue.Dequeue(Timeout, out item))
{
string message = System.Text.Encoding.UTF8.GetString(item.Body);
DoSomethingMethod(message);
channel.BasicAck(item.DeliveryTag, false);
}
}
catch (EndOfStreamException ex)
{
// this is likely due to some connection issue -- what am I to do?
}
catch (Exception ex)
{
// should never happen, but lets say my DoSomethingMethod(message); throws an exception
// presumably, I'll just log the error and keep on going
}
}
}
}
public IConnection Connection
{
get
{
if (_connection == null) // _connection defined in class -- private static IConnection _connection;
{
_connection = CreateConnection();
}
return _connection;
}
}
private IConnection CreateConnection()
{
ConnectionFactory factory = new ConnectionFactory()
{
HostName = "RabbitMqHostName",
UserName = "RabbitMqUserName",
Password = "RabbitMqPassword",
};
// why do we need to set this explicitly? shouldn't this be the default?
factory.AutomaticRecoveryEnabled = true;
// what is a good value to use?
factory.NetworkRecoveryInterval = TimeSpan.FromSeconds(5);
// what is a good value to use? How is this different from NetworkRecoveryInterval?
factory.RequestedHeartbeat = 5;
IConnection connection = factory.CreateConnection();
return connection;
}
RabbitMQ features
The documentation on RabbitMQ's site is actually really good. If you want to recover queues, exchanges and consumers, you're looking for topology recovery, which is enabled by default. Automatic Recovery (which is enabled by default) includes:
Reconnect
Restore connection listeners
Re-open channels
Restore channel listeners
Restore channel basic.qos setting, publisher confirms and transaction settings
The NetworkRecoveryInterval is the amount of time before a retry on an automatic recovery is performed (defaults to 5s).
Heartbeat has another purpose, namely to identify dead TCP connections. There are more to read about that at RabbitMQ's site.
Code sample
Writing reliable code for recovery is tricky. The EndOfStreamException is (as you suspect) most likely due to network problems. If you use the management plugin, you can reproduce this by closing the connection from there and see that the exception is triggered. For production-like applications, you might want to have a set of brokers that you alternate between in case of connection failure. If you have several RabbitMQ brokers, you might also want to guard yourself against long-term server failure on one or more of the servers. You might want to implement error strategies, like requeuing the message, or using a dead letter exchange.
I've been thinking a bit of these things and written a thin client, RawRabbit, that handles some of these things. Maybe it could be something for you? If not, I would suggest that you change the QueueingBasicConsumer to an EventingBasicConsumer. It is event driven, rather than thread blocking.
var eventConsumer = new EventingBasicConsumer(channel);
eventConsumer.Received += (sender, args) =>
{
var body = args.Body;
eventConsumer.Model.BasicAck(args.DeliveryTag, false);
};
channel.BasicConsume(queue, false, eventConsumer);
If you have topology recovery activated, the consumer will be restored by the RabbitMQ Client and start receiving messages again.
For more granular control, hook up event handlers for ConsumerCancelled and Shutdown to detect connectivity problems and Registered to know when the consumer can be used again.

Exceptions connection delay opening of the software

I am having some problems to handle the connection to a database. What I did essentially was to create a class called Database, in this I placed all the methods required to connect to the database, check whether the connection is active and update a control depending on the status of the connection. This works well, control is updated and there are no problems, but when the connection on your computer is absent, the program delays its opening because they generated a series of exceptions in particular that:
MySql.Data.MySqlClient.MySqlException (0x80004005)
The exception occurs in the method isAvailable(), this method checks whether the connection is available or not, and returns true if there is, respectively, or false if it is absent.
public static bool isAvailable()
{
try
{
string connStr = #"Server=xxx;Port=xxx;Database=xxx;Uid=xxx;Pwd=xxx;";
connection = new MySqlConnection(connStr);
connection.Open();
return true;
}catch(Exception ex)
{
connection.Close();
Console.WriteLine(ex.ToString());
return false;
}
}
This method is invoked by checkStatus that contains the following:
public static void checkStatus()
{
if(isAvailable() == false)
{
updateStatus("false");
}
else
{
updateStatus("true");
}
}
checks whether it is true or false and returned respectively to the back passes the value to another method that simply brings up a warning Canvas red or green in the interface ...
checkStatus is called in every aspect of my other classes to check the connection status (before executing a query, pretty much the structure is as follows):
string stm = "SELECT * FROM history";
MySqlCommand cmd = new MySqlCommand(stm, Database.Database.Connection);
Database.Database.checkStatus(); //here
MySqlDataReader rdr = cmd.ExecuteReader();
Within the class constructor call the method isAvailable Database to check if the connection is actually open or not.
At this point I do not understand why the exceptions while managing the program delays the appearance when the user executes it. If no exceptions occur when you start, the program takes about 5 seconds to boot, while with the exceptions I arrived at 1 minute!
What am I doing wrong?
Making a connection to the database server may take quite some time due to many factors: network conditions, server load, authentication overhead etc. Hence the driver (the code behind MySqlConnection) needs to wait an appropriate amount of time to decide whether the connection can or cannot be established. The default timeout is, apparently in your case, 60 seconds (or a multiple of the default 15 seconds as per documentation due to several requests?).
What you can do is lower the timeout by means of the ConnectionTimeout argument in the connection string — see the documentation here. However, bear in mind that by setting it to, say, 5 seconds, you program may end up failing in legitimate cases where it would otherwise succcessfuly connect to the server. I suggest you perform database operations or at least the initial check asynchronously and display a 'please wait' message meanwhile.

Linq to Sql: Change Database for each connection

I'm working on an ASP.NET MVC application which uses Linq to SQL to connect to one of about 2000 databases. We've noticed in our profiling tools that the application spends a lot of time making connections to the databases, and I suspect this is partly due to connection pool fragmentation as described here: http://msdn.microsoft.com/en-us/library/8xx3tyca(v=vs.110).aspx
Many Internet service providers host several Web sites on a single
server. They may use a single database to confirm a Forms
authentication login and then open a connection to a specific database
for that user or group of users. The connection to the authentication
database is pooled and used by everyone. However, there is a separate
pool of connections to each database, which increase the number of
connections to the server.
There is a relatively simple way to avoid this
side effect without compromising security when you connect to SQL
Server. Instead of connecting to a separate database for each user or
group, connect to the same database on the server and then execute the
Transact-SQL USE statement to change to the desired database.
I am trying to implement this solution in Linq to Sql so we have fewer open connections, and so there is more likely to be a connection available in the pool when we need one. To do that I need to change the database each time Linq to Sql attempts to run a query. Is there any way to accomplish this without refactoring the entire application? Currently we just create a single data context per request, and that data context may open and close many connections. Each time it opens the connection, I'd need to tell it which database to use.
My current solution is more or less like this one - it wraps a SqlConnection object inside a class that inherits from DbConnection. This allows me to override the Open() method and change the database whenever a connection is opened. It works OK for most scenarios, but in a request that makes many updates, I get this error:
System.InvalidOperationException: Transaction does not match
connection
My thought was that I would then wrap a DbTransaction object in a similar way to what I did with SqlConnection, and ensure that its connection property would point back to the wrapped connection object. That fixed the error above, but introduced a new one where a DbCommand was unable to cast my wrapped connection to a SqlConnection object. So then I wrapped DbCommand too, and now I get new and exciting errors about the transaction of the DbCommand object being uninitialized.
In short, I feel like I'm chasing specific errors rather than really understanding what's going on in-depth. Am I on the right track with this wrapping strategy, or is there a better solution I'm missing?
Here are the more interesting parts of my three wrapper classes:
public class ScaledSqlConnection : DbConnection
{
private string _dbName;
private SqlConnection _sc;
public override void Open()
{
//open the connection, change the database to the one that was passed in
_sc.Open();
if (this._dbName != null)
this.ChangeDatabase(this._dbName);
}
protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
{
return new ScaledSqlTransaction(this, _sc.BeginTransaction(isolationLevel));
}
protected override DbCommand CreateDbCommand()
{
return new ScaledSqlCommand(_sc.CreateCommand(), this);
}
}
public class ScaledSqlTransaction : DbTransaction
{
private SqlTransaction _sqlTransaction = null;
private ScaledSqlConnection _conn = null;
protected override DbConnection DbConnection
{
get { return _conn; }
}
}
public class ScaledSqlCommand : DbCommand
{
private SqlCommand _cmd;
private ScaledSqlConnection _conn;
private ScaledSqlTransaction _transaction;
public ScaledSqlCommand(SqlCommand cmd, ScaledSqlConnection conn)
{
this._cmd = cmd;
this._conn = conn;
}
protected override DbConnection DbConnection
{
get
{
return _conn;
}
set
{
if (value is ScaledSqlConnection)
_conn = (ScaledSqlConnection)value;
else
throw new Exception("Only ScaledSqlConnections can be connections here.");
}
}
protected override DbTransaction DbTransaction
{
get
{
if (_transaction == null && _cmd.Transaction != null)
_transaction = new ScaledSqlTransaction(this._conn, _cmd.Transaction);
return _transaction;
}
set
{
if (value == null)
{
_transaction = null;
_cmd.Transaction = null;
}
else
{
if (value is ScaledSqlTransaction)
_transaction = (ScaledSqlTransaction)value;
else
throw new Exception("Don't set the transaction of a ScaledDbCommand with " + value.ToString());
}
}
}
}
}
I don't think that's going to work off a single shared connection.
LINQ to SQL works best with Unit of Work type connections - create your connection, do your atomically grouped work and close the connection as quickly as possible and reopen for the next task. If you do that then passing in a connection string (or using custom constructor that only passes a tablename) is pretty straight forward.
If factoring your application is a problem, you could use a getter to manipulate the cached DataContext 'instance' and instead create a new instance each time you request it instead of using the cached/shared instance and inject the connection string in the Getter.
But - I'm pretty sure this will not help with your pooling issue though. The SQL Server driver caches connections based on different connection string values - since the values are still changing you're right back to having lots of connections active in the connection string cache, which likely will result in lots of cache misses and therefore slow connections.
I think I figured out a solution that works for my situation. Rather than wrapping SqlConnection and overriding Open() to change databases, I'm passing the DBContext a new SqlConnection and subscribing to the connection's StateChanged event. When the state changes, I check to see if the connection has just been opened. If so, I call SqlConnection.ChangeDatabase() to point it to the correct database. I tested this solution and it seems to work - I see only one connection pool for all the databases rather than one pool for each db that has been accessed.
I realize this isn't the ideal solution in an ideal application, but for how this application is structured I think it should make a decent improvement for relatively little cost.
I think, that the best way is making UnitOfWork pattern with Repository pattern to work with Entity Framework. Entity Framework has FirstAsync, FirstOrDefaultAsync, this helped me to fix the same bug.
https://msdn.microsoft.com/en-us/data/jj819165.aspx

RasConnectionNotification after computer resumes from sleep

I've got a project called DotRas on CodePlex that exposes a component called RasConnectionWatcher which uses the RasConnectionNotification Win32 API to receive notifications when connections on a machine change. One of my users recently brought to my attention that if the machine comes out of sleep mode, and attempts to redial the connection, the connection goes into a loop indicating the connection is already being dialed even though it isn't. This loop will not end until the application is restarted, even if done through a synchronous call which all values on the structs are unique for that specific call, and none of it is retained once the call completes.
I've done as much as I can to fix the problem, but I fear the problem is something I've done with the RasConnectionNotification API and using ThreadPool.RegisterWaitForSingleObject which might be blocking something else in Windows.
The below method is used to register 1 of the 4 change types the API supports, and the handle to associate with it to monitor. During runtime, the below method would be called 4 times during initialization to register all 4 change types.
private void Register(NativeMethods.RASCN changeType, RasHandle handle)
{
AutoResetEvent waitObject = new AutoResetEvent(false);
int ret = SafeNativeMethods.Instance.RegisterConnectionNotification(handle, waitObject.SafeWaitHandle, changeType);
if (ret == NativeMethods.SUCCESS)
{
RasConnectionWatcherStateObject stateObject = new RasConnectionWatcherStateObject(changeType);
stateObject.WaitObject = waitObject;
stateObject.WaitHandle = ThreadPool.RegisterWaitForSingleObject(waitObject, new WaitOrTimerCallback(this.ConnectionStateChanged), stateObject, Timeout.Infinite, false);
this._stateObjects.Add(stateObject);
}
}
The event passed into the API gets signaled when Windows detects a change in the connections on the machine. The callback used just takes the change type registered from the state object and then processes it to determine exactly what changed.
private void ConnectionStateChanged(object obj, bool timedOut)
{
lock (this.lockObject)
{
if (this.EnableRaisingEvents)
{
try
{
// Retrieve the active connections to compare against the last state that was checked.
ReadOnlyCollection<RasConnection> connections = RasConnection.GetActiveConnections();
RasConnection connection = null;
switch (((RasConnectionWatcherStateObject)obj).ChangeType)
{
case NativeMethods.RASCN.Disconnection:
connection = FindEntry(this._lastState, connections);
if (connection != null)
{
this.OnDisconnected(new RasConnectionEventArgs(connection));
}
if (this.Handle != null)
{
// The handle that was being monitored has been disconnected.
this.Handle = null;
}
this._lastState = connections;
break;
}
}
catch (Exception ex)
{
this.OnError(new System.IO.ErrorEventArgs(ex));
}
}
}
}
}
Everything works perfectly, other than when the machine comes out of sleep. Now the strange thing is when this happens, if a MessageBox is displayed (even for 1 ms and closed by using SendMessage) it will work. I can only imagine something I've done is blocking something else in Windows so that it can't continue processing while the event is being processed by the component.
I've stripped down a lot of the code here, the full source can be found at:
http://dotras.codeplex.com/SourceControl/changeset/view/68525#1344960
I've come for help from people much smarter than myself, I'm outside of my comfort zone trying to fix this problem, any assistance would be greatly appreciated!
Thanks! - Jeff
After a lot of effort, I tracked down the problem. Thankfully it wasn't a blocking issue in Windows.
For those curious, basically once the machine came out of sleep the developer was attempting to immediately dial a connection (via the Disconnected event). Since the network interfaces hadn't finished initializing, an error was returned and the connection handle was not being closed. Any attempts to close the connection would throw an error indicating the connection was already closed, even though it wasn't. Since the handle was left open, any subsequent attempts to dial the connection would cause an actual error.
I just had to make an adjustment in the HangUp code to hide the error thrown when a connection is closed that has already been closed.

Categories