Should C# ClientWebSocket be declared static or instance? - c#

I am currently creating a .NET6 C# trading API client application and the API has two different WebSocket endpoints.
I'm wondering whether the ClientWebSocket object (System.Net.WebSockets) should be declared static or instance. I'm aware HttpClient should be declared static to prevent unnecessary new connections so I'm wondering if the same rationale applies to ClientWebSocket.
From my testing so far my impression is that the ClientWebSocket should be connected and disconnected manually as required, opposed to leaving it connected without any requirement (i.e. just pinging and ponging), and therefore instance objects may be fine to use. Put another way: if websocket connections are explicitly managed there does not appear to be an issue of 'connection re-use' like HttpClient and therefore instances are ok.
Having said that, another design option might be to declare the ClientWebSocket as static and just maintain an open connection + auto re-connect as long as the application is running.
My current design is to have two instance objects of ClientWebSocket, one for each API endpoint. They will be newed up each time a connection is needed.
Any thoughts appreciated.

Related

Properly shutting down MongoDB database connection from C# 2.1 driver?

I am just getting started with integrating MongoDB into my application and I have ran into a few questions. In my application I am using the newest 2.1 version of the MongoDB C# driver and only using MongoDB for application logging.
Currently before showing my main application Form I first check to see if mongod.exe is running and if not I start it. Then when my main Form is shown it opens a connection to the database for use seen below.
public void Open()
{
Client = new MongoClient("mongodb://localhost:27017");
Database = Client.GetDatabase(DBName);
Collection = Database.GetCollection<BsonDocument>(ColName);
}
My question is how I should properly shutdown this connection when my application is closing?
Also are there in considerations I should take into account in leaving mongod.exe running versus exiting it each time the application closes?
I have searched a few times trying to figure out if there is a proper way to shutdown the connection but have found nothing very specific. There is an old SO post (that I can't seem to find now) mentioning a .Dispose method, though I cannot seem to find it in the newest driver nor from my IDE's auto complete.
As of today's version of MongoDB (v2.0.1.27 for MongoDB.Driver), there's no need to close or dispose of connections. The client handles it automatically.
From the docs:
A MongoClient object will be the root object. It is thread-safe and is all that is needed to handle connecting to servers, monitoring servers, and performing operations against those servers.
[...]
It is recommended to store a MongoClient instance in a global place, either as a static variable or in an IoC container with a singleton lifetime. However, multiple MongoClient instances created with the same settings will utilize the same connection pools underneath.
There's a partial/old list of thread-safe MongoDB classes in this SO answer.
The question seems to have been already kinda asked here at When should i be opening and closing MongoDB connections?
If it's accepted answer,
I would leave the connection open as re-creating the connection is
costly. Mongo is fine with lots of connections, open for a long time.
What you ideally should do is to share the connection with all parts
of your application as a persistent connection. The C# driver should
be clever enough to do this itself, so that it does not create too
many connections, as internally it uses "connection pooling" that
makes it even re-use connections. The docs say: "The connections to
the server are handled automatically behind the scenes (a connection
pool is used to increase efficiency)."
works fine for you then all well and good. Even the MongoDB C# driver's quick tour page lends the same advice -
Typically you only create one MongoClient instance for a given cluster
and use it across your application. Creating multiple MongoClients
will, however, still share the same pool of connections if and only if
the connection strings are identical.
Otherwise, I think you can simply put your call to create the connection in a using(){} code block. It automatically calls the dispose method for you (as it implements the IDisposable pattern). You should use this block for any resource you want disposed.
From my experience, the correct way is as answered, but even following these recommendations, I still was having random EndOfStreamException. It seems that some problems are caused by the internet provider closing the connection after some time.
I Solved it by adding:
MongoClientSettings settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
settings.SslSettings = new SslSettings() { EnabledSslProtocols = SslProtocols.Tls12 };
settings.MaxConnectionIdleTime = TimeSpan.FromSeconds(30);

PerCall InstanceContextMode behaviour of WCF service

I have a WCF service, exposing a ServiceContract with basicHttpBinding, so from my understanding InstanceContextMode will be set to PerCall (as basicHttpBinding doesn't support sessions) and ConcurrenyMode will be set to Single.
The client of this WCF is a windows service, which invokes 4 different operations on the service at the same time, within the service we have used a singleton class and there are few Static variables. We have been facing a problem where in a wrong value is getting passed to some of the DB Stored Procedures.
With PerCall InstanceContextMode and Single concurrency mode, i understand a new service instacne in created for every call and hence i am thinking that even though there are some singleton classes (we have not made it thread safe) in the service implementation and static variables all the objects will be destroyed, but we have observed running a SQL profiler that on old value is getting passed the DB.
We have written our WCF service code in a kind of 3-tier architecture, i mean ServiceClass, BusinessLogicLayer and DataAccessLayer, with PerCall set as instanceContextMode when we say the service instance is destroyed after the client request is finished, does it mean we destroy all the object in ServiceClass,BusinessLogicLayer and DataAccessLayer?
Pls help me understand what could be going wrong
The InstanceContextMode PerCall means a new class of your service is instantiated per call. Static variables in your AppDomain will not be reset. They will stay between service calls, as long as your AppPool is not recycled.
Remove all statics including singletons from your code. They never belonged to your architecture anyway.
Many WCF requests share the same AppDomain. Static variables are per AppDomain. WCF does nothing to those variables (in fact it cannot even find out they exist). You are responsible for maintaining them.
WCF does not destroy any of your objects because neither does WCF understand what they mean nor does it know they exist.
The settings you mentioned are only relevant to the service object.
My usual advice regarding stateful server apps: You are working under bad practices here. You need to ensure thread-safety. In case the worker process shuts down (deployment, automatic restart, server reboot, app bug crashing the process, power loss, hardware failure, ...) your data is lost.
Though it is restricted in any way static variables needs to be protected for thread safe as a best practice. Static variables will not be destroyed till the service is stopped / app pool recycle.
Using static variables for the data which changes are not recommended for distributed web farms, because those are not safer over a failover.
Visual Studio 2012 and above comes with a Memory profiler. But the simple thing can be done using a counter in the object constructors (only on testing) which can tell if there is a new instance created on every request or not.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall,ConcurrencyMode=ConcurrencyMode.Single)]
public class TestServiceWithStaticVars : ITestServiceWithStaticVars
{
static int instanceCount = 0;
public TestServiceWithStaticVars()
{
Interlocked.Decrement(ref instanceCount);
}
public string GetInstanceCount()
{
return string.Format("You have created {0} instance", instanceCount);
}
Let you know if better instance counter available to use with ease.
[Edit] as I can't comment now.
Re-assigning the static variable will take the new value as you said. The static variables are loaded in to HighFrequencyHeap for frequent access. For more information http://www.codeproject.com/Articles/15269/Static-Keyword-Demystified

RabbitMQ in a WCF webservice, model usage and performance

I need to call a RabbitMQ RPC Service from within a C# WCF Web service hosted in IIS.
We have this working OK, but being a good little soldier I was reading the RabbitMQ client documentation and it states the following "IModel should not be shared between threads".
My understanding is that in RabbitMQ an IModel is actually a socket connection.
this would mean that for every call the WCF service makes it's needs to create an IModel and dispose of it once completed.
This would seem to me to be somewhat excessive on performance and socket usage and I am wondering if my understanding is actually correct, or if there are other options available like using a connection pool of IModels between threads.
Any suggestions would be gratefully received. Here's a sample of the code I'm using below, the rabbitMQ connection is actually initialized in the Global.asax, I just have it there to you can see the usage.
var connectionFactory = new ConnectionFactory();
connectionFactory.HostName = "SampleHostName";
connectionFactory.UserName = "SampleUserName";
connectionFactory.Password = "SamplePassword";
IConnection connection = connectionFactory.CreateConnection();
// Code below is what we actually have in the service method.
var model = connection.CreateModel();
using (model)
{
model.ExchangeDeclare("SampleExchangeName", ExchangeType.Direct, false);
model.QueueDeclare("SampleQueueName", false, false, false, null);
model.QueueBind("SampleQueueName", "SampleExchangeName", "routingKey" , null);
// Do stuff, like post messages to queues
}
IModel is actually a socket connection
This is incorrect. IConnection represents a connection :) Model was introduced in order to allow several clients to use the same tcp connection. So Model is a "logical" connection over a "physical" one.
One of tasks Model does is splitting and re-assembling large messages. If message exceeds certain size, it is split into frames, frames are labeled and are assembled back by receiver. Now, imagine that 2 threads send large messages... Frame numbers will be messed up, and you will end up with Frankenstein message which consists of random parts of 2 messages.
You are right assuming that Model creation have some cost. Client sends a request to server to create a model, server creates a structure in memory for this model, and sends model Id back to the client. It is done over tcp connection which is already open, so no overhead due to establishing connection. But there is still some overhead because of network round trip.
I'm not sure about WCF binding, but base rabbit's .net library does not provide any pooling for models. If it is a problem in your case, you'll have to come up with something on your own.
You need a single IModel object for each session. This is pretty normal for network-based API's. For example the Azure Table Storage client is exactly the same.
Why, well you can't have a single Channel with multiple concurrent communication streams running over them.
I would expect that a certain level of caching to occur (e.g. DNS) which would reduce the overhead of creating subsequent IModel instances.
Performance is alright when doing the same thing with Azure Tables so it should be perfectly fine with IModel. Only attempt to optimise this when you can prove you have a real need.

How to persist a webservice reference instance in an SQLCLR stored procedure?

At the moment I have a windows service written in C# that waits for a message in SQL Server Service Broker, and upon receipt calls a webservice method with details passed in the message.
I want to replace this with an SQLCLR stored procedure that calls the webservice directly, which I've found to be quite simple. I can then call this using internal activation.
However it needs to create a new instance of the webservice for each method, and from experience I've found this takes some time. In the windows service I create it with lazy instantiation in a static class, but I understand static fields can't be used to store information in SQLCLR.
Is there a way to persist this webservice reference?
Edit: Here is the lazy instantation code referencing the singleton I'd like to persist:
static class WsSingleton
{
static MWs.MWS mWS = null;
public static MWs.MWS GetMWS()
{
if (mWS == null)
{
mWS = new MWs.MWS();
mWS.Credentials = new System.Net.NetworkCredential("user", "password", "domain");
}
return mWS;
}
}
it needs to create a new instance of the webservice for each method
Do you mean the client has to instantiate a proxy for each HTTP call it makes? If that's what you mean you shouldn't have to persist any reference. An internal activated procedure is launched when there are messages to process and it can stay active and running. Such a locl state could be the proxy instance used to place the WWW calls. Typically the procedure runs a loop and keeps state on the stack as local variables of loop method. See Writing Service Broker Procedures for more details. To be more precise, your code should not RECEIVE one message at a time, but a set of messages.
But I would advise against doing what you're doing. First and foremost, making HTTP calls from SQLCLR is a bad idea. Doing any sort of blocking in SQLCLR is bad, and doing blocking on waiting for bits to respond from the intertubez is particularly bad. The internal SQL Server resources, specially workers, are far too valuable and few to waste them waiting for some WWW service to respond. I would advise keeping things like they are now, namely have hte HTTP call occur from an external process.
A second comment I have is that you may be better of using a table as a queue. See Using tables as Queues. One typical problem with queueing HTTP calls is that the WWW is very unreliable and you have to account for timeouts and retries. Using a table as a quueu can achieve this easier than a true Service Broker Queue. With SSB you'd have to rely on conversation timers for reliable retries, and it makes your activation logic significantly more complicated.

What's the simplest way to connect to a .NET remote server object

Given that my client code knows everything it needs to about the remoting object, what's the simplest way to connect to it?
This is what I'm doing at the moment:
ChannelServices.RegisterChannel(new HttpChannel(), false);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(IRemoteServer), "RemoteServer.rem", WellKnownObjectMode.Singleton);
MyServerObject = (IRemoteServer)Activator.GetObject(
typeof(IRemoteServer),
String.Format("tcp://{0}:{1}/RemoteServer.rem", server, port));
The first two lines are in the server-side code, for marshaling out the server object, yes?
In that case, yes, the third line is the simplest you can get at client-side.
In addition, you can serve out additional server-side objects from the MyServerObject instance, if you include public accessors for them in IRemoteServer interface, so, accessing those objects become the simple matter of method calls or property accesses on your main server object, so you don't have to use activator for every single thing:
//obtain another marshalbyref object of the type ISessionManager:
ISessionManager = MyServerObject.GetSessionManager();
WCF.
I have used IPC before there was a WCF, and believe me, IPC is a bear. And it isn't documented fully/correctly.
What’s the simplest way to connect to a .NET remote server object? WCF.

Categories

Resources