Assume a WCF service with ServiceBehavior.ConcurrencyMode = Single.
When exactly does the service start blocking for concurrent calls?
For example, say we have two clients: Slow and Fast.
At time 0 Slow starts a slow service call that includes a huge chunk of data.
At time 1 Fast makes a fast service call.
At time 2 the slow data finally arrives and the service code is executed on the server.
Assuming buffers configured in WCF to be larger than the huge chunk, which call will get executed first?
In other words, does blocking start when all call data has been received at the server side or when the client initiates the call?
Is the service blocked during the data transfer or only during code execution?
Unless you configure InstanceContextMode to Single as well both calls will be executed concurrently. So suppose that you have InstanceContextMode set to Single.
I didn't test it but I would expect such behavior. Concurrency mode is service behavior so it takes place once the service instance / instance context is resolved. In buffered mode that happens after whole message is received in streaming mode it should happen after message headers are received. So in case of buffered transport I would expect that fast client will be processed first and in case of streamed transport it depends if message headers from slow client was already received.
But as I wrote before this is only my expectation.
Related
I have a system, that request data from a WCF webservice
it is like so:
WCF1 calls WCF2, WCF2 calls WCF3 and WCF3 do its job and returns response
My problem here is some of the operations takes a long time "about 2 min" to process
So if WCF1 send a request that takes long of time, and then another request from WCF1 that should take a second, it will wait until the first request finishes
i read about the problem, some of users said to use
<ServiceBehavior(ConcurrencyMode:=ConcurrencyMode.Multiple, InstanceContextMode:=InstanceContextMode.PerCall)> _
this doesn't solve the problem 100%
Can u please advice
I do not think those settings will solve your problem.
From the source:
In PerCall instancing, concurrency is not relevant, because each
message is processed by a new InstanceContext and, therefore, never
more than one thread is active in the InstanceContext.
Bottom line, because you are using PerCall activation, there is no point in adding the ConcurrencyMode.Multiple as each incoming request will get its own instance of the service class to handle its request.
You should try to narrow down what is really causing the performance problem. Look at the underlying code that your WCF services are calling.
EDIT
From another SO post.
In terms of behavior: ConcurrencyMode does not matter for a PerCall
service instance.
In terms of performance: A PerCall service that is
ConcurrencyMode.Multiple should be slightly faster because its not
creating and acquiring the (unneeded) thread lock that
ConcurrencyMode.Single is using.
I have got the following scneario:
Our .NET client calls our WCF service - which in turn calls an external third party service to retrieve some data. Once the data is retrieved, our WCF service sets some values and then returns the control back to the client. The process of calling the external service has to be synchronous.
My problem is that this all works in a low load environment but when load gets high then we start queueing multiple requests, the WCF service starts timing out. We have set the "sendTimeout" property for the binding to 5 seconds and it times out after that.
I've tried replacing the external service with a mocked out local version and that handles the load OK but on the same hand the call to external service on it own is very quick - around 0.5 second. I can only presume that the timeouts are happening because too many requests were queued and WCF service couldn't respond within those allocated 5 seconds.
I have tried the following:
Set the values of maxConcurrentCalls, maxConcurrentSessions & maxConcurrentInstances to very high numbers
Set the value of system.net - connectionManagement - maxconnection to a very high number
Does any one have any ideas about what we can do in this scneario?
does your cpu peak during these high load times ? if not then you might be running out of threads. Make your wcf service that receives the original call asynchronous, and then call the external service asynchronously.
you will have to use asnyc pattern throughout your call chain to make sure nothing is blocking the thread.
http://msdn.microsoft.com/en-us/library/ms731177.aspx
I'm working on a WCF service to help our new code interoperate with a legacy system. The process goes like this:
Client calls the service with a request for the legacy system.
Service writes the request into a database.
Legacy system services request from the DB in its own time and writes results back into the DB (updating a status flag to say results are ready).
Client retrieves results by calling a second service method, which polls the DB until the ready flag is set.
Just before returning the results, the service updates the status flag to client has results, so that the related DB rows can be deleted.
My concern is the race condition at the last step. I can see this happening:
Service updates status to client has results.
Client times out after waiting for the service to poll the DB.
Service tries to return results. Hilarity ensues.
One way to solve this would be to have three service calls instead of two: the second call retrieves results, and the last one is an explicit acknowledgement by the client that it has them. I'd like to know whether there is a way which doesn't impose this extra "protocol" burden on the client though.
I've looked briefly into using transactions in WCF, and it sounds like they might be able to do what I need. The client (optionally) starts a transaction, flows it to the service, which uses it if it's there, and commits it when done. This seems as if it implicitly does the "third call".
Does this idea have any merit? Any disadvantages that you can see? Are there any other avenues I could explore?
Using transaction flow is possible but flowing transaction in polling scenario (in each poll call) is terrible architecture. What you generally need is transaction flow for the real read operation where service modifies the record and returns data back to the client. The client will commit the transaction and it will commit changes performed by the service.
Using transactional processing places some additional requirements on your service and clients.
Another approach can be transactional MSMQ:
Client calls the service with a request for the legacy system = client sends a message to the service's queue
Service writes the request into a database = service processes the message from its queue
Legacy system services request from the DB in its own time and writes results back into the DB (updating a status flag to say results are ready).
Service polls the database and places messages to correct client queues. Placing the message and modifying database records runs in transaction
Client processes incoming message
Transactional queue allows transactional reading (the message is removed from the queue only if transaction is committed) and writing (the message is added to the queue only if transactions is committed). That will allow deleting records before the client reads the message because the message will remain in the queue until he successfully reads it (or until it timeouts and even after that it can be passed to some error queues).
In both cases you should think about clients who will consume the service. Transaction flowing can be interoperable but not every web service stack supports it. MSMQ is not interoperable.
Why not reduce the likelihood of the client timing out by doing this instead:
Client calls service with a request for the legacy system.
Service writes the request into a database.
Legacy system services request from the DB in its own time and writes results back into the DB (updating a status flag to say results are ready).
Client calls a service to find out whether the results are ready. NB. no polling: just returns with an immediate yes or no.
If the results are NOT ready, client waits a bit and then goes back to step 4.
If the results ARE ready, call the service to retrieve the results. The service can update the status to "Client has results" at that point.
By doing this, the client won't be waiting for the service call in step 4. to return for a prolonged period, and the chances of a timeout should be minimal.
However, you're never going to be 100% certain that the client has received the results unless the client makes a final service call to say so. (What if, for example, the client dies after making the very last request?)
I have a simple WCF need - basically clients running in isolation and a server so really client/server intially.
WCF helps us decouple the service layer and practise a SOA approach for scale.
All we are doing on the server (per call/multiple concurrency) is writing to a db and then performing some IO for another system which will have immediate use for - but this might change as (unknown) requirements build.
Speed: We need the service to be literally quick as possible: 1 second is OK - 2 is slow - and some errors need to be sent back immediately.
I was considering using server async patterns, queues (MSMQ), Azure, to allow the service method to queue and return quickly. NB However, some processing might be 'online' in the WCF service (db write) with an immediate return with response/error, others could be offline (IO). Disadvantage: This requires a means to callback the client if there is a show-stopper error and design and development scales accordingly.
i) Although WCF allows for the service I see the technology as providing an interprocess comm channel and perhaps the actual service operations should run in win services. Eg. WCF writes to a db which a long-running service polls and picks up. As the system gets bigger and bigger some operations may be genuine fire and forget long running - which complete or are needed hours after. We can take these out of the immediate loop. This is true decoupling even if it slows us down. A WCF method can't pass to a service unless it is calling another WCF service and can't call a windows service!
From an architectural viewpoint, is it OK to have some operations complete and return, and others pass to a true bus or service (by some mechanism)? Am I over-engineering this?
ii) As all the operations of db and IO will take say 1 or 2 seconds max I feel I might just call the service aysnc from the client and wait for it to return and then marshal back to the client UI. This is also simple. This might prove a wrong decision in the long run but having said that, all service layer ops would be in a seperate dll so that these could be called by another service for later scale. A method call could be marked as immediate or queue for processing, say.
Thoughts?
From an architectural viewpoint, is it
OK to have some operations complete
and return, and others pass to a true
bus or service (by some mechanism)? Am
I over-engineering this?
It is OK, all depends on detailed requirements.
Thought #1
Have operations return unique request ID and one operation that provides status by request ID.
Thought #2
Have operations return result if they are done within X number of seconds or request ID.
The client sends a lot of messages to the server from a single thread, over a single WCF channel.
The client sends the message with BeginMyMethod(x, b) as it does not wish to block while they get processed.
We have reliable messaging turned on, as we don’t wish to lose any messages, or have them get out of order.
However the messages are being despatched on multiple threads on the server, so are being process out of order.
We can’t have the server being single threaded, as we don’t wish a long running request from one client to block other clients.
So I just wish to process all the messages that come from a single client (over a single channel) in order with only one message from each cleint being processed at a time.
This would be easy for raw socket programming, however how to I get WCF to work as I wish?
I am now thinking that ConcurrencyMode.Reentrant does not behave well when used with InstanceContextMode.Single If I set use ConcurrencyMode.Single the messages are kept in order, but my call-backs deadlock.
(The test that gets the messages out of order has no callbacks and does not make any outgoing WCF calls, so I would expect ConcurrencyMode.Reentrant to behave the same as ConcurrencyMode.Single in that given test, but it does not)
I a not using any WCF config files, the code is:
serviceHost = new ServiceHost(this);
serviceHost.AddServiceEndpoint(
typeof(IAllEngineManagersAsyncCallbacks),
new NetTcpBinding(SecurityMode.None, true),
endPointAddress);
I have now worked round this problem by:
Changing all my call-backs from the server to the client to be OneWay
Using a dispatcher in the client before passing on any callback from the server, so client code never calls the sever from within a call-back
The client call-back object is marked with CallbackBehavior(UseSynchronizationContext=false, ConcurrencyMode=ConcurrencyMode.Single)
When running in Winform or WPF I use SynchronizationContext.Post to depatch the callbacks
When the cleint is a Console or a Windows server I use a custom depatcher.
So letting me use ConcurrencyMode.Single on both the server and the client.
It is now working as expected.
(BeginMyMethod(x, b) is still being used to send messaged from the client to the server)
(ConcurrencyMode.Reentrant seems to sometimes release the lock even when the WCF call is not made on the some thread that is processing the incoming message, it is just not a useful as Reentrant was in DCOM)
If you are using the generated BeginXXX async-methods, these are executed on a ThreadPool thread.
So although you've send the messages in a defined order, nobody guarantees you in which order the ThreadPool executes the requests.
I think that Reentrant mode implies that you allow messages be processed out of order. Normal behavior of such service would be: get message, put in queue for internal threads to process, and when it's done notify client about result. So maybe your service get messages in proper order but some of them are quiker to process and return earlier than others?