How does WCF handle instancing and concurrency? - c#

I try to understand how WCF handles instancing, concurrency and threading.
For example, if I configure the instance context mode to PerCall and concurrency mode to singe, every request creates a new instance of the WCF service. What does that mean related to the threads, which a created server side?
I guess that instancing and concurrency is not strong related to threading. Is it right that, to the given example, every request is queued by the "main" I/O ThreadPool to be executed by the worker thread? Or is every request creating a new instance and thread that executes this request?

if I configure the instance context mode to PerCall and concurrency
mode to singe, every request creates a new instance of the WCF
service. What does that mean related to the threads, which a created
server side?
If you use Per-Call instancing then the service instances are all single threaded, as each incoming request is serviced by a new instance of the service. So specifying concurrency is not relevant in this scenario.
I guess that instancing and concurrency is not strong related to
threading
I'm not sure how you arrive at this conclusion.
Addressing comments below this post:
In a Per-Call mode, for each call we create an instance of the
service. If we are in a single thread mode, there is one thread
handling these instances so we serve requests in a sequential way
These two statements are contradictory. If we create a new instance per request, then the service does not handle multiple requests sequentially. It will create a new instance per request.
(In PerCall mode) if the concurrency mode is multiple, there are many threads executing
the instances methods so we serve request in parallel way
This is not correct. Multiple requests will each be handled by their own service instance.
Handling a call in a service instance takes one thread. The call handling code may well be multi-threaded but this is internal to the service and WCF concurrency mode does not affect the execution of call handling code.
Other calls to the service will result in new instances of the service being created. So while you certainly can set concurrency mode to multiple, you will never get more than one thread handling requests to a service instance.
Therefore setting concurrency mode to multiple in per call instancing does not make any practical difference to the behavior of the service.

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 )]

PerSession vs. PerCall

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.

How to implement thread inside a web service?

I need to make a thread inside my web service, to check on some data in my database every specific time.
I would not do that. The thread would die with the application pool. Create a windows service which checks the database using a Thread or a Timer.
Why would you want to do that?
If your service is per-call (i.e. not singleton), all the resources involved in servicing a request is supposed to be released right after the call. If you spawn a thread, the request will be kept alive until your thread completes.
Also, checking on data in a database periodically does not really make sense in a web service call, which should complete within a very short time anyway, otherwise you kill scalability.
You're probably referring to a singleton web service, in that one single server object services requests. In this case, you'll need to create the singleton object first -- most likely in a Windows service that is started automatically.
Your database polling is most likely used to cache certain popular values so that servicing requests do not need to hit the database itself. In this case, your service is actually a middle-tier layer. Unless you know that data in the database changes very frequently, consider replacing the database polling with triggers in the database that calls the web service to update new data.

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

Asynchronous Remoting calls

We have a remoting singleton server running in a separate windows service (let's call her RemotingService). The clients of the RemotingService are ASP.NET instances (many many).
Currently, the clients remoting call RemotingService and blocks while the RemotingService call is serviced. However, the remoting service is getting complicated enough (with more RPC calls and complex algorithms) that the asp.net worker threads are blocked for a significantly long time (4-5 seconds).
According to this msdn article, doing this will not scale well because an asp.net worker thread is blocked for each remoting RPC. It advises switching to async handlers to free up asp.net worker threads.
The purpose of an asynchronous handler
is to free up an ASP.NET thread pool
thread to service additional requests
while the handler is processing the
original request.
This seems fine, except the remoting call still takes up a thread from the thread pool.
Is this the same thread pool as the asp.net worker threads?
How should I go about turning my remoting singleton server into an async system such that I free up my asp.net worker threads?
I've probably missed out some important information, please let me know if there is anything else you need to know to answer the question.
The idea behind using the ThreadPool is that through it you can control the amount of synchronous threads, and if those get too many, then the thread pool automatically manages the waiting of newer threads.
The Asp.Net worked thread (AFAIK) doesn't come from the Thread Pool and shouldn't get affected by your call to the remoting service (unless this is a very slow processor, and your remoting function is very CPU intensive - in which case, everything on your computer will be affected).
You could always host the remoting service on a different physical server. In that case, your asp.net worker thread will be totally independent of your remoting call (if the remoting call is called on a separate thread that is).

Categories