Concurrency of thread - wcf

I have a WCF application (vb) which works fine but when a user requests information while the server is doing a call to another user, everybody hangs!

When you configure your service, there are two things you need to configure:
InstanceContextMode - which determines how many service instances are created to service the client requests, try use PerCall/PerSession if possible as they allows for the most concurrency.
ConcurrencyMode - which determines if each service instance is single-threaded or multi-threaded.
Based on the information you've provided so far, I'd recommend changing these two settings and see if it solves your problem:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyService : IMyService { ... }
I put a blog post together of the things I learnt whilst doing some performance work on our WCF services a little while back, maybe it'd be of help:
http://theburningmonk.com/2010/05/wcf-improve-performance-with-greater-concurrency/

Related

Why service behaviour 'ReleaseServiceInstanceOnTransactionComplete = false' is required with 'ConcurrencyMode.Multiple' on Transactions enabled

One of my WCF service operation has transaction enabled-
[OperationBehavior(TransactionScopeRequired = true)]
public Car UpdateCar(Car c)
{
}
Earlier, I was running this service with InstanceContextMode as PerCall and ConcurrencyMode as Multiple which was getting me the below error-
An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll
Additional information: The 'InventoryManager' service is configured with ReleaseServiceInstanceOnTransactionComplete set to true, but the ConcurrencyMode is not set to Single. The ReleaseServiceInstanceOnTransactionComplete requires the use of ConcurrencyMode.Single.
In order to solve above error, i set 'ReleaseServiceInstanceOnTransactionComplete' to false and this did the trick.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall
, ConcurrencyMode = ConcurrencyMode.Multiple
, ReleaseServiceInstanceOnTransactionComplete = false)]
Can someone please help to understand how disposing the service instance with 'PerCall' and 'Multiple' case solved this problem. What is the problem WCF thinks if I release service instance.
These are purely design decision made by the WCF designers.
From the book programming WCF services:
The WCF architects did not trust developers to properly manage state of their sessionful service in the face of transactions. Therefore they decided to treat a sessionful transactional service as a per-call service to enforce a proper state aware programming model.
And a Percall service with ConcurrencyMode.Multiple is useless of course. At the service load time WCF verifies that if TransactionScopeRequired is true for at least one operation when ReleaseServiceOnTransactionComplete is true, the ConcurrencyMode is ConcurrencyMode.Single.
That is the behaviour you are observing.
https://books.google.nl/books?id=PvNrurEhmiEC&pg=PA348&lpg=PA348&dq=per-session+transactional+services&source=bl&ots=CiDuKxG_Ox&sig=UvkgF1yTxmirsf_Zb452bW86AmQ&hl=nl&sa=X&ved=0ahUKEwiYjrX-uPrPAhWGfhoKHTgWBckQ6AEIHDAA#v=onepage&q=per-session%20transactional%20services&f=false
The designers were probably right with the decision to let WCF handle concurrency in the face of transactions. It is hard to manage your own concurrency in a service.
For instance, I had a service that also acted as a client of another service.
When changing the concurrency mode to Multiple the service would sometimes throw the exception when trying to open the client connection:
"System.InvalidOperationException: Cannot make a call on this channel because a call to Open() is in progress."
This is the kind of hard to debug kind of bugs the designers wanted to avoid (I think)
The default implementation of Service is
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
If there is a TransactionScope defined on any Operations on your Service implementation:
[OperationBehavior(TransactionScopeRequired = true)]
public void Method() { }
The default Service implementation will be dropped to
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
And this attribute will prevent it and will regain your PerSession semantics:
[ServiceBehavior(ReleaseServiceInstanceOnTransactionComplete = false)]
Take note that this is necessary if you have sessionful service and atleast one TransactionScopeRequired = True, on one of your operations.

what is the purpose of wcf ConcurrencyMode

i am very new in WCF. so often gaze for wcf code & article. after viewing many code i often stuck for very basic things and got no elaborate discussion for the below question. so here are my few basic question....and looking for details discussion with sample situation and with sample code.
what is ConcurrencyMode ??
actually what ConcurrencyMode does.....what it determines??
there are few ConcurrencyMode available and those
are Multiple,Reentrant and Single
which concurrent mode one should use in what kind of situation.
what will be the best choice. thanks
It depends on what you need. If you need a single instance of your service to be instantiated for the life time of the application you might want to use single. You might do this for instance if instantiating that service was extremely expensive for some reason and it was not called very often so you weren't concerned about multiple threads hitting it at the same time.
[ServiceBehavior(Namespace = "http://somenamespace", InstanceContextMode = InstanceContextMode.Single)]
public sealed class ServiceWithExpensiveDictionary : IServiceWithExpensiveDictionary, IDisposable
{
private DataCacheFactory factory;
private ConcurrentDictionary<string, DataCache> dataCacheDictionary;
/// <summary>
/// Constructor
/// </summary>
public ServiceWithExpensiveDictionary()
{
factory = new DataCacheFactory();
dataCacheDictionary = new ConcurrentDictionary<string,DataCache>();
}
In the code above, I want the ConcurrentDictionary instance to be around for all callers of the service as I'm putting expensive objects into it.
You might use session if you were intending users to have stateful long-running conversations with your api.
You might use per call if your services were stateless and service instantiation was cheap.
It really depends on what you want to do.
There is also a nice question related to this here. It also touches on throttling which you might also be interested in:-
WCF ConcurrencyMode Single and InstanceContextMode PerCall

Simple WCF "Hello world" service occupies only one CPU core under load

I have a simple "Hello world" service based on basicHttpBinding. The service is hosted on a quad-core CPU.
When I run load tests only one core is occupied (95%), and the others three approximately 4-8%.
Why are the other cores not used for proccessing?
Setting ConcurrencyMode = ConcurrencyMode.Multiple didn't help.
Configure a ServiceBehavior for your service.
WCF uses ConcurrencyMode=ConcurrencyMode.Single by default. That mode runs all requests to your service in one thread.
With ConcurrencyMode.Single, WCF does not call again into the object
so long as the method is running. After the operation returns the
object can be called again.
One CPU core is used to run that thread.
Add the attribute below for your service to use all the CPUs:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
Be careful with service state when you enable that mode. You may need to implement your own locking if you change state.
Check ConcurrencyMode Enumeration for more details.
Also make sure that your client makes four calls simultaneously (implement multi-threading in client). Without that you still will have sequential one-thread calls processing even if your server supports multi-threading.
Update after checking the code:
Your WCF method doesn't do any work that can load the CPU. Please replace your methods with some heavy CPU-using function (calculate hashes or factorial) and re-check.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class HelloService : IHelloService
{
public string HelloWorld()
{
return "Hello world";
}
}
The API docs for BasicHttpBinding say this:
Any instance members are not guaranteed to be thread safe.
This implies that a single BasicHttpBinding instance should not be called from multiple threads in parallel, and therefore cannot be spread across multiple CPUs/CPU cores.

WCF Service Behavior to add an operation to my services

I'd like to create a service behavior which adds an extra service operation to my service. This way I can add the behavior to any of my services (existing and future) and my service will all be able to perform this extra service operation. (e.g. ping or returns some other service information)
I'm not sure what to do here to achieve what I want, What I've tried to do so far is to implement a service behavior which tries to modify the service description. Should I add an endpoint and then specify a new contract on that?
public class MyOperationBehavior : IServiceBehavior
{
void IServiceBehavior.ApplyDispatchBehavior(
ServiceDescription desc, ServiceHostBase host)
{
ServiceEndpointCollection sec = svcDesc.Endpoints;
ServiceEndpoint se = new ServiceEndpoint()
{
se.Address = "DoMyOperation";
se.Binding = "basicHttpBinding";
se.Contract = MyCustomContract;
}
}
}
One of the benefits of using services is that you are exposing a well-defined and fairly static set of operations to your consumers.
I'm not sure how being able to dynamically add service operations at runtime would benefit your consumers.
I would suggest that if you need to change your service contract on a per-consumer basis then it may indicate that your service composition is probably incorrect for the needs of your consumers.
Apologies this does not answer your question directly, and appreciate that re-work on the scale suggested may be outside current development scope.
I've found what I was looking for in this article on Dynamically adding methods to a WCF service without having to add it to each service contract.
But I also believe using WS-Discovery is a much better way of achieving what I want: exposing information about a service without having to touch the service contracts

Utilizing multiple service contracts over the same WCF channel or session

I'm in the process of writing a duplex WCF service using NetTcpBinding, and I've run into an architecture question that I think I know the answer to, but hope that I'm wrong.
Our service is stateful, and we've selected NetTcpBinding with PerSession InstanceContextMode. For various reasons, this is something that we require. I'm trying to break up our larger interface (where large blocks of the operations would not apply to many clients) into multiple smaller interfaces with the operations logically grouped. While it's simple enough to have a single service implementation implement all of the contracts, I'm not sure if it's possible to have multiple service contracts share a single channel (or, more to my requirement, a single session), and I'd definitely need to be able to do that in order to make this work.
I could, of course, include everything on one contract and throw FaultExceptions when an invalid operation is performed, but I'd really like to be able to break these up and not even add an endpoint for inapplicable contracts. Is what I'm looking for possible?
TL;DR Version:
I need to be able to do this:
[ServiceContract]
public interface IServiceA
{
[OperationContract]
void Foo();
}
[ServiceContract]
public interface IServiceB
{
[OperationContract]
void Bar();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service : IServiceA, IServiceB
{
...
}
And be able to establish one session from the client to the service but use both IServiceA and IServiceB.
The default instance provider over a sessionful channel will give you an instance per connection in your case. You can however extend the instance provider to pick up an existing object from your own cache and return the same object.
How you correlate instances will be upto you using some special message header etc. The underlying channel/Connection will be different for each proxy and also use differnt buffers / concurrency models but you can allow service model to use the same instance.
http://msdn.microsoft.com/en-us/magazine/cc163590.aspx