PerSession vs. PerCall - c#

What's the general rule of thumb to decide whether to use PerSession or PerCall?
I have a slightly heavy (I think..) WCF service, containing CRUD methods to about 80 tables.
I have separated the WCF service into 7 contracts within 1 service, (i.e., 7 end points within 1 service) such that each contract takes care of its own domain, for example I have a Sales contract, so all sales related tables, and its corresponding operations are within the sales "bounded context"
So my WCF service structure looks something like this:
public partial class ABCService : ISalesService
{
//CRUD methods of all tables related to Sales
}
public partial class ABCService : IMarketingService
{
//CRUD methods of all tables related to Marketing
}
public partial class ABCService : ICustomerService
{
//CRUD methods of all tables related to Customer
}
public partial class ABCService : IProductService
{
//CRUD methods of all tables related to Products
}
My concern with PerCall is that, because I have a fairly large DB/WCF service, I'm afraid that the amount of resources consumed by each call, multiplied by the number of users and the rate of which they call the service, would be far too great.
I do not know the fine details, but I have read that creating a Channel Proxies are expensive operations.
Oh, I'm using hand coded proxies instead of VS's Add service reference to consume my WCF service.
So, my question is, which should I use? PerSession or PerCall?
Update:
I do not need to maintain state between calls.
I'm using NetTCP bindings

In my opinion, to take a decision consider these two points
For going with InstanceContextMode.PerSession - If your users have some session values stored on the WCF service on the server.
For going with InstanceContextMode.PerCall - If your users have nothing stored in session on the WCF service on the server i.e. WCF service requires No per user settings required to store in memory. Requires scalability.
Some points regarding When-And-Why,
InstanceContextMode.PerCall
If your service is stateless and scalable, i.e. benefits are similar to HTTP as it is also stateless.
If service has light-weight initialization code (or none at all).
If your service is single threaded.
Example scenario: For any 1000 client requests in a given time period in a PerCall situation, there will only be 100 objects instantiated for 100 active calls. Secondly if server were to crash then in PerCall situation the only errors that would occur would be to the 100 actual requests that were in progress (assuming fast failover). The other 900 clients could be routed to another server on their next call.
InstanceContextMode.PerSession
If your service has to maintain some state between calls from the same client.
If your service has light-weight initialization code (or none at all). Even though you are only getting a new instance for each client proxy, you still want to be careful about having expensive initialization code in a constructor.
Example scenario: For any 1000 client requests in a given time period in a PerSession situation you may have 1000 objects instantiated on the server but only 100 are actually active in call at any moment. And thus instantiated PerSession objects could be a waste of resources and may impact the ability to serve requests under load. Secondly if server were to crash then in PerSession all 1000 clients who have a session on that server would lose their session and be unable to complete their work.
Reference links:
MSDN - WCF Instancing, Concurrency, and Throttling
SO - Per-Call vs Per-Session
MSDN - Using Sessions in WCF context

The reason you don't see many answers to this type of question online is that it depends. What I would do is try it out -- then open up perfmon on the server where you are hosting the service and add the counters for your service. Just google wcf performance manager counters if you aren't familiar.
The good news is that WCF makes changing the setup pretty easy.
If you are concerned with the cost of instantiating a proxy on the client side, remember that perCall is a service behavior, not a client behavior. Even if you set the service instance context to PerCall, you can still create one instance of your proxy and make a bunch of method calls from that proxy. All perCall means is that when you make a call, an instance of the service is created, your method is called, and the instance of the service is torn down again. If you don't have any expensive initialization on the service instance (i.e. if they're basically static methods) you're probably ok with per call.

Related

Can WCF handle simultaneous calls to the same endpoint?

I am developing WCF application under Windows Service which is exposing one endpoint. There can be about 40 remote clients who will connect to this endpoint over local area network at the same time. My question is whether WCF can handle multiple calls to the same endpoint by queuing them? No request from any client can be lost. Is there anything special I have to consider when developing application to handle simultaneous calls?
You can choose whether the requests should be handled asynchronously or synchronously one after another.
You can set this behavior via the InstanceContextMode settings. By default WCF handles requests ByCall which means one instance of your service will be created for each incoming request. This allows you to handle multiple requests in parallel.
Alternatively you can configure your service to spin off only one instance which ensures each request is handled after the other. This effectively is the "queuing" you mentioned. You can set this behavior via InstanceContextMode.Single. By chosing this mode, your service becomes a singleton. So this mode ensures there's only one instance of your service, which may come in handy in some cases. The framework handles the queuing.
Additionally you could set ConcurrencyMode.Multiple which allows your single instance to process multiple requests in parallel (see Andrew's comment).
However, be aware that the queued requests aren't persisted in any way. So if your service gets restarted, the not yet finished requests are lost.
I'd definitely recommend to avoid any kind of singleton if possible.
Is there anything that prevents you from chosing the parallel PerCall-mode?
For more details have a look at this: http://www.codeproject.com/Articles/86007/ways-to-do-WCF-instance-management-Per-call-Per
Here are some useful links:
https://msdn.microsoft.com/en-us/library/ms752260(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/hh556230(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.servicemodel.servicebehaviorattribute(v=vs.110).aspx
To answer your question, no calls will be lost whatever you choose. But if you need to process them in order, you probably should use this setup for your service
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, EnsureOrderedDispatch = true )]

Persist object in C# .NET Web Service

Am stuck on what am sure is a fundamental and easy to solve problem in WCF, just need to be guided towards the right way.
I have a large object (which is actually a trained text classifier) that I need to expose through a Web Service in C# .NET. The classifier object can be loaded from disk when the service initially starts, but I don't want to keep loading it from disk for every request (the object that services requests currently occupies about 6 GB in memory, and it takes a while to keep loading it from disk for every request), so instead I want to persist that object in memory throughout all requests to that web service, and the object should only be loaded when the service starts (instead of loading it when the first web request triggers it).
How would I go about doing that?
Thanks for any help!
Probably the easiest way is to create your service as a singleton. This involves specifying InstanceContextMode = InstanceContextMode.Single in a ServiceBehavior attribute on your service class definition.
However it is very questionable if sending a 6GB object over the wire using WCF is advisable. You can run into all sorts of service availability issues with this approach.
Additionally, singletons are not scalable within a host (can be only one instance per host), although you can host multiple singleton services and then load-balance the requests.
The way I've done this in projects that I've had the problem with in the past is to self host the WCF service inside a Windows Service.
I've then set the data storage object up inside the service as a singleton that persists for the life of the service. Each WCF service call then gets the singleton each time it needs to do something with the data.
I would avoid running in IIS simply because you don't have direct control of the service's lifetime and therefore don't have enough control of when things are disposed and instantiated.

Concurrent requests with a static value and webservices

I have a web server (ASP.NET - Mono 2.6.7) with a value static float x in it and two methods : getX() and setX(newX). I also have two clients one is a pc with c# console application and the other one is a mobile device with android (ksoap2). Both can access the web server.
What I do not know is : if my mobile device try to do a getX() while my pc is doing a setX(newX), will it result any trouble ?
Thanks.
It's not a good practice to have a state-full implementation for services. You can have different instances serving multiple requests. This is the case in ASP.NET web services. In WCF, using configuration, you can change instancing behavior. For example, you can have a single instance serving all requests (few of them can be concurrent) - in case, one has mutable state (as in your case), you have to synchronize the access to the state. Thread synchronization on shared state will create a bottleneck in serving the requests because at the most only one request thread can access the state. Further, you cannot scale horizontally (i.e. web farm scenario where requests will be served from multiple machines). If you choose to have multiple instances serving the request then you need to externalize the state e.g. put it into the database. In such case, you will incur in the penalty of accessing external data source (which can be much higher than thread synchronization) but you will have scalable design.
Roughly-speaking, a web service class/object should not be stateful in itself. You can store state, but it's usually externally, for example in a database.
This is because, depending on configuration, there's no guarantee that it will be the same instance of the class for every request for every client.

Understanding Asp.net web service

Can you please answer to the following questions to enlighten me about web services.
What is the lifecycle of web service ? When the class which represents my web service gets instanced and when it's start running (executing) ?
Is it there new instance created for every webMethod call ? And what happens if there are multiple simultaneous requests for same or different web method ?
When to open connection to remote resource, that the onnection is ready before any requests. And this connection must persist through whole lifetime of web service.
Thank you in advace for all answers.
Webservices are nothing more than ASP.NET pages communicating on the SOAP protocol (XML over HTTP). Each method have its own round-trip (like a page, so new instances are created by default). ASP.NET thread pool is used for running a webservice. As web programmer you don't have lot of control over how thread pool is used since it depends on many external factors (system resources, concurrent page requests...).
If you mean database connections by 'Opening connection to remote resources' these connections also are pooled by Connection Pool of ADO.NET and it will be managed automatically. If you external resources are heavy use Singleton webservice model and load external resources in constructor. Don't use singleton patteron on a database connection (It has its own pooling mechanism). You should take care of concurrency issues for your static variables if you are choosing Singleton pattern.
At the end I should say living in managed-world of programming is easier than ever. Most of the time somebody is caring about our doubts.
That depends; You have two instancation models.
"Single Call" (an instance is created for each call made to the service)
"Singleton" (an instance is created on the first call and reused as long as the process remains alive).
See answer 1; Eleboration; Yes, each call get's its own instance
I would seperate that away from the actual Web Service class. You can use another singleton approach to achieve this functionality.
Hope this helps,

How does one set up a WCF ServiceHost within a Windows Service that can access stateful information within the Windows Service

I have a written a Windows Service in C#. It is functioning and performing well. I have added a WCF service to the Windows service to enable client applications to connect to the Windows service and obtain stateful information from the Windows service.
I configured the WCF service to be a singleton, so that the same service instance is used to handle all requests from all clients as follows:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
All clients are able to connect and have access to the same stateful information within the WCF service. However, I am running into the following peculiar behavior.
Revised:
I instantiate the WCF service contract within my Windows Service. Any stateful information assigned at the time of instantiation is available to all clients that connect to the service.
However, any stateful information added to the service contract instance later directly from the Windows Service (not by clients) is not visible to clients that connect to the service. It is as if there are two instances of the service contract: One for the Windows Service and one for the clients that connect to the WCF service.
What is the recommended (best) way to instantiate a WCF service and have it be able to access stateful information available within the Windows Service?
I would recommend doing an end-run around this by holding your state in a static member, so that it doesn't matter whether or not WCF is creating a new instance for each call or reusing one. This solves the problem and simplifies the code.
Why does the WCF service have to have stateful information? Couldn't that be stored in a database and accessed when needed?
WCF does allow Singleton instances for services - but it's usually discouraged to use this, unless you absolutely, positively have to. Typically, it's easier and scales much better if you can store the stateful info in e.g. a database table and let clients access that using a normal, per-call WCF service.
UPDATE:
OK, another idea: you'll always only gonna have a single ServiceHost anyway. If you choose the "per-call" instanciation mode (as recommended by all leading experts), the ServiceHost will allocate a thread pool of worker threads which will then service the incoming requests.
Why does the WCF service need to be a singleton? Couldn't you use "per-call" and still get at the stateful information in the NT Service?
A request comes in and an instance of your service object (the service class, implementing the service interface) is created. How do you access the stateful information in the NT service right now? Couldn't you do that from the newly created service instance, too - when you actually need it?
If you have stateful information being held in the NT Service, you'll need to make sure any concurrent access will be properly handled - that's totally independent of whether your WCF service class is a singleton or not.
UPDATE 2:
Using the 'OperationContext.Current.Host', you can access the ServiceHost that hosts a given service instance inside the service method being executed - not sure if you can access the actual NT service instance. But if you create your own custom ServiceHost descendant, which has an additional property "ListOfClients", you should be able to access that list at any time, from any service instance running.
MIND YOU: since there are possibly any number of service requests being processed at any given time, reading the list must be thread-safe, and updating the list from the Windows NT Service is even more "risky" and needs to take these concurrency issues into account! Lock the list if you need to update it - otherwise, you'll have unpredictable results.
Marc
Setting InstanceContextMode.Single will cause the ServiceHost to construct a single instance of your service and use that for all calls. But it sounds like you would like to construct the instance yourself, and populate it with a reference to some shared state. If so, that's called the "well-known instance" pattern and can be accomplished by passing the instance to the ServiceHost constructory, like so:
var svc = new MyServiceClass(state);
var host = new ServiceHost(svc, new Uri(..), ...);
...
ServiceHost will use the instance you pass in for all calls.
An important consideration when using the Single instance mode (whether the object is "well-known" or constructed by the ServiceHost) is threading. By default WCF will only allow one thread to execute concurrently per service instance. So in the PerCall instance mode, since you'll have multiple service instances, you can support multiple concurrent threads which will improve throughput under normal conditions. But with the Single instance mode you only have one service instance so you'd only run one thread at a time. It depends on the service, but it often makes sense then to switch the concurrency mode to Multiple, which will allow multiple concurrent threads into your service instance, but requires that your service implementation be thread-safe.
Some good docs here: http://msdn.microsoft.com/en-us/library/ms731193.aspx

Categories