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.
Related
I have a WCF service that will serve multiple clients.
They will have operation like 'Accept Suggested Match' or 'Reject Suggested Match'.
I would like all the operations to be run serially, but I am afraid this will have an impact on performance.
From what I saw - the default (and most used) instancing is 'Per Call' and the default concurrency mode is single.
So is it true I would need to use 'Single' mode in the concurrency ?
And how bad of an impact is it ?
(I estimate tens of clients using the system at the most).
Is there any way to enjoy both worlds ?
Use parallel computing (the service communicates with a database) and still perform the operations serially ?
In this post I read about 'Instance mode = Per Call and Concurrency = Single':
For every client instance, a single thread will be allocated.
For every method call, a new service instance will be created.
A single thread will be used to serve all WCF instances generated from a single client instance.
It seems like this doesn't guarantee to me that operation calls will be performed serially !
For example, if this happens :
CLIENT ALPHA calls 'Operation A'
CLIENT ALPHA calls 'Operation B'
CLIENT BETA calls 'Operation C'
From what I read - it says 'A single thread will be used to serve all WCF instances generated from a single client instance'. This sounds to me like it means that CALL 1 and CALL 2 would be performed serially, but CALL 3 might be performed between them, because it is from a different client thread.
Is this true ? Is there no way to make sure that calls are handled at the order they arrive ?
And can someone tell me if it is a bad practice or are there real world scenarios where it is accepted and recommended to use this method of communication in WCF.
Thank you very much
I think there are 3 ways to answer this question
A direct answer
An alternative approach for situations where you control the clients and the server
An alternative approach where you don't control the clients
I'd like to give answers 2 and 3 first (because I think they are better) but I will give a direct answer at the end...I promise!
I believe your problem is not that you need to process messages in the order they are received by the service, it is that since you have independent clients, you cannot guarantee that they are received by the service in the same order they are sent from the clients.
Consider your example of clients ALPHA and BETA. Even though client ALPHA might send the request to call operation 2 before client BETA calls operation C, you have no way of knowing what order they will be received by the service. This means that even if you process them at the server in the order they are received, this might still be the "wrong" order.
If you agree with this, carry on reading. If not, go straight to the direct answer at the bottom of this post ;o)
Approach 1: Use WS-Transactions
If you control both the service and the clients, and if the clients are capable of implementing WS-* SOAP protocols (e.g. .Net WCF clients). Then you could use the WS-Transaction protocol to make sure that operations from a single client that are intended to be processed in a single long-running transaction are definitely done that way.
For details of how to do WS-Transcation with WCF, look at
http://msdn.microsoft.com/en-us/library/ms752261.aspx
Following you example with clients ALPHA and BETA, this would enable client ALPHA to
Start a transaction
Call operation 1
Call operation 2
Commit the transaction
The effect of the ALPHA starting a transaction on the client is to flow that transaction through to the server so it can create a DB transaction which guarantees that operation 1 and operation 2 complete together or not at all.
If client BETA calls operation 3 while this is going on, it will be forced to wait until the transaction commits or aborts. Note that this might cause operation 3 to time out in which case BETA would need to handle that error.
This behaviour will work with any InstanceContextMode or ConcurrencyMode.
However, the drawback is that these kind of long running, distributed transactions are not generally good for scalability. Today you have 10s of client, but will that grow in the future? And will the clients always be able to implement WS-Transaction? If so, then this could be a good approach.
Approach 2: Use an "optimistic" type approach
If you need to support many different client types (e.g. phones, browsers etc.) then you could just allow the operations to happen in any order and make sure that the service and client logic can handle failures.
This might sound bad, but
you can use database transactions on the server side (not the WS-Transaction ones I mentioned above) to make sure your database is always consistent
each client can synchronise its own calls so that in your example, ALPHA would wait for call 1 to complete OK before doing call 2
The drawback here is that you need to think carefully about what failure logic you need and make sure the client and service code is robust and behaves appropriately.
In your example, I mentioned that ALPHA can synchronise its own calls, but if BETA calls operation 3 after ALPHA calls operation 1 but before it calls operation 2, it could be that
Operation 2 will fail (e.g. operation 3 has deleted a record that operation 2 is trying to update) in which case you need to handle that failure.
Operation 3 will overwrite operation 3 (e.g. operation 3 updates a record and the operation 2 tries to update the same record). In this case you need to decide what to do. Either you can let operation 2 succeed in which case the updates from BETA are lost. Or you could have operation 2 detect that the record has changed since it was read by ALPHA and then fail, or maybe inform the user and have them decide if they want to overwrite the changes.
For a discussion on this in the context of MS Entity Framework see
http://msdn.microsoft.com/en-us/library/bb738618.aspx
for a general discussion of it, see
http://en.wikipedia.org/wiki/Optimistic_concurrency_control
Again, in WCF terms, this will work with any ConcurrencyMode and InstanceContextMode
This kind of approach is the most common one used where scalability is important. The drawback of it is that the user experience can be poor (e.g. they might have their changes overwritten without being aware of it).
Direct answer to the original question
If you definately need to make sure messages are processed in series, I think you are looking for InstanceContextMode.Single
http://msdn.microsoft.com/en-us/library/system.servicemodel.instancecontextmode.aspx
This means that a single instance of the service class is created for the lifetime of the service application. If you also use ConcurrencyMode = Single or ConcurrencyMode = Reentrant this then means that your service will only process one message at a time (because you have a single instance and it is single threaded) and the messages will be processed in the order they are received.
If you use ConcurrencyMode = multiple then your single service instance will process multiple messages at the same time on different threads so the order of processing is not guaranteed.
How bad a performance impact this will have will depend on how long each service call takes to execute. If you get 10 per second and each takes 0.1 second it will be fine. If you get 20 per second and each normally takes 0.1 seconds, you will see a 100% increase in the average time.
I am trying to understand how instances with WCF works. I have a WCF service which the InstanceContextMode set to PerCall (so for each call of every client a new instance will be created) and ConcurrencyMode set to Single (so the service instance is executing exactly one or no operation call at a time).
So with this I understand that when a client connects a new instance is created. But what happens when the client leaves the service. Does the instance die. The reason I ask is because I need to implement a ConcurrentQueue in the service. So a client will connect to the service and put loads of data to be processed and then leave the service. The workers will work of the queue. After the work is finished I need the instance to be destroyed.
Basically, learning from the "WCF Master Class" tought by Juval Lowy, per-call activation is the preferred choice for services that need to scale, i.e. that need to handle lots of concurrent requests.
Why?
With the per-call, each incoming request (up to a configurable limit) gets its own, fresh, isolated instance of the service class to handle the request. Instantiating a service class (a plain old .NET class) is not a big overhead - and the WCF runtime can easily manage 10, 20, 50 concurrently running service instances (if your server hardware can handle it). Since each request gets its own service instance, that instance just handles one thread at a time - and it's totally easy to program and maintain, no fussy locks and stuff needed to make it thread-safe.
Using a singleton service (InstanceContextMode=Single) is either a terrible bottleneck (if you have ConcurrencyMode=Single - then each request is serialized, handled one after another), or if you want decent performance, you need ConcurrencyMode=Multiple, but that means you have one instance of your service class handling multiple concurrent threads - and in that case, you as a programmer of that service class must make 100% sure that all your code, all your access to variables etc. is 100% thread-safe - and that's quite a task indeed! Only very few programmers really master this black art.
In my opinion, the overhead of creating service class instances in the per-call scenario is nothing compared to the requirements of creating a fully thread-safe implementation for a multi-threaded singleton WCF service class.
So in your concrete example with a central queue, I would:
create a simple WCF per-call service that gets called from your clients, and that only puts the message into the queue (in an appropriate fashion, e.g. possibly transforming the incoming data or something). This is a quick task, no big deal, no heavy processing of any kind - and thus your service class will be very easy, very straightforward, no big overhead to create those class instances at all
create a worker service (a Windows NT service or something) that then reads the queue and does the processing - this is basically totally independent of any WCF code - this is just doing dequeuing and processing
So what I'm saying is : try to separate the service call (that delivers the data) from having to build up a queue and do large and processing-intensive computation - split up the responsibilities: the WCF service should only receive the data and put it into a queue or database and then be done with it - and a second, separate process should do the processing/heavy-lifting. That keeps your WCF service lean'n'mean
Yes, per call means, you will have a new insance of the service per each connection, once you setup the instance context mode to percall and ConcurrencyMode to single, it will be single threaded per call. when the client leaves, done with the job, your instance will dispose. In this case, you want to becareful not to create your concurrentqueue multiple times, as far as i can imagine, you will need a single concurrentqueue? is that correct?
I would recommend you to use IntanceContextMode=Single and ConcurrencyMode to Mutli threaded. This scales better.if you use this scheme, you will have a single concurrent queue, and you can store all your items within that queue.
One small note, ConcurrentQueue, has a bug, you should be aware of, check the bug database.
I have found myself responsible for carrying on the development of a system which I did not originally design and can't ask the original designers why certain design decisions were taken, as they are no longer here. I am a junior developer on design issues so didn't really know what to ask when I started on the project which was my first SOA / WCF project.
The system has 7 WCF services, will grow to 9, each self-hosted in a seperate console app/windows service. All of them are single instance and single threaded. All services have the same OperationContract: they expose a Register() and Send() method. When client services want to connect to another service, they first call Register(), then if successful they do all the rest of their communication with Send(). We have a DataContract that has an enum MessageType and a Content propety which can contain other DataContract "payloads." What the service does with the message is determined by the enum MessageType...everything comes through the Send() method and then gets routed to a switch statement...I suspect this is unusual
Register() and Send() are actually OneWay and Async...ALL results from services are returned to client services by a WCF CallbackContract. I believe that the reson for using CallbackContracts is to facilitate the Publish-Subscribe model we are using. The problem is not all of our communication fits publish-subscribe and using CallbackContracts means we have to include source details in returned result messages so clients can work out what the returned results were originally for...again clients have a switch statements to work out what to do with messages arriving from services based on the MessageType (and other embedded details).
In terms of topology: the services form "nodes" in a graph. Each service has hardcoded a list of other services it must connect to when it starts, and wont allow client services to "Register" with it until is has made all of the connections it needs. As an example, we have a LoggingService and a DataAccessService. The DataAccessSevice is a client of the LoggingService and so the DataAccess service will attempt to Register with the LoggingService when it starts. Until it can successfully Register the DataAccess service will not allow any clients to Register with it. The result is that when the system is fired up as a whole the services start up in a cascadeing manner. I don't see this as an issue, but is this unusual?
To make matters more complex, one of the systems requirements is that services or "nodes" do not need to be directly registered with one another in order to send messages to one another, but can communicate via indirect links. For example, say we have 3 services A, B and C connected in a chain, A can send a message to C via B...using 2 hops.
I was actually tasked with this and wrote the routing system, it was fun, but the lead left before I could ask why it was really needed. As far as I can see, there is no reason why services cannot just connect direct to the other services they need. Whats more I had to write a reliability system on top of everything as the requirement was to have reliable messaging across nodes in the system, wheras with simple point-to-point links WCF reliabily does the job.
Prior to this project I had only worked on winforms desktop apps for 3 years, do didn't know any better. My suspicions are things are overcomplicated with this project: I guess to summarise, my questions are:
1) Is this idea of a graph topology with messages hopping over indirect links unusual? Why not just connect services directly to the services that they need to access (which in reality is what we do anyway...I dont think we have any messages hopping)?
2) Is exposing just 2 methods in the OperationContract and using the a MessageType enum to determine what the message is for/what to do with it unusual? Shouldnt a WCF service expose lots of methods with specific purposes instead and the client chooses what methods it wants to call?
3) Is doing all communication back to a client via CallbackContracts unusual. Surely sync or asyc request-response is simpler.
4) Is the idea of a service not allowing client services to connect to it (Register) until it has connected to all of its services (to which it is a client) a sound design? I think this is the only design aspect I agree with, I mean the DataAccessService should not accept clients until it has a connection with the logging service.
I have so many WCF questions, more will come in later threads. Thanks in advance.
Well, the whole things seems a bit odd, agreed.
All of them are single instance and
single threaded.
That's definitely going to come back and cause massive performance headaches - guaranteed. I don't understand why anyone would want to write a singleton WCF service to begin with (except for a few edge cases, where it does make sense), and if you do have a singleton WCF service, to get any decent performance, it must be multi-threaded (which is tricky programming, and is why I almost always advise against it).
All services have the same
OperationContract: they expose a
Register() and Send() method.
That's rather odd, too. So anyone calling will first .Register(), and then call .Send() with different parameters several times?? Funny design, really.... The SOA assumption is that you design your services to be the model of a set of functionality you want to expose to the outside world, e.g. your CustomerService might have methods like GetCustomerByID, GetAllCustomersByCountry, etc. methods - depending on what you need.
Having just a single Send() method with parameters which define what is being done seems a bit.... unusual and not very intuitive / clear.
Is this idea of a graph topology with
messages hopping over indirect links
unusual?
Not necessarily. It can make sense to expose just a single interface to the outside world, and then use some internal backend services to do the actual work. .NET 4 will actually introduce a RoutingService in WCF which makes these kind of scenarios easier. I don't think this is a big no-no.
Is doing all communication back to a
client via CallbackContracts unusual.
Yes, unusual, fragile, messy - if you can ever do without it - go for it. If you have mostly simple calls, like GetCustomerByID - make those a standard Request/Response call - the client requests something (by supplying a Customer ID) and gets back a Customer object as a return value. Much much simpler!
If you do have long-running service calls, that might take minutes or more to complete - then you might consider One-Way calls which just deposit a request into a queue, and that request gets handled later on. Typically, here, you can either deposit the answer into a response queue which the client then checks, or you can have two additional service methods which give you the status of a request (is it done yet?) and a second method to retrieve the result(s) of that request.
Hope that helps to get you started !
All services have the same OperationContract: they expose a Register() and Send() method.
Your design seems unusual at some parts specially exposing only two operations. I haven't worked with WCF, we use Java. But based on my understanding the whole purpose of Web Services is to expose Operations that your partners can utilise.
Having only two Operations looks like odd design to me. You generally expose your API using WSDL. In this case the WSDL would add nothing of value to the partners, unless you have lot of documentation. Generally the operation name should be self-explanatory. Right now your system cannot be used by partners without having internal knowledge.
Is doing all communication back to a client via CallbackContracts unusual. Surely sync or asyc request-response is simpler.
Agree with you. Async should only be used for long running processes. Async adds the overhead of correlation.
Few methods in my WCF service are quite time taking - Generating Reports and Sending E-mails.
According to current requirement, it is required so that Client application just submits the request and then do not wait for the whole process to complete. It will allow user to continue doing other operations in client applications instead of waiting for the whole process to finish.
I am in a doubt over which way to go:
AsyncPattern = true OR
IsOneWay=true
Please guide.
It can be both.
Generally I see no reason for WCF operation to not be asynchronous, other than developer being lazy.
You should not compare them, because they are not comparable.
In short, AsyncPattern=True performs asynchronous invocation, regardless of whether you're returning a value or not.
OneWay works only with void methods, and puts a lock on your thread waiting for the receiver to ack it received the message.
I know this is an old post, but IMO in your scenario you should be using IsOneWay on the basis that you don't care what the server result is. Depending on whether you need to eventually notify the client (e.g. of completion or failure of the server job) then you might also need to look at changing the interface to use SessionMode=required and then using a Duplex binding.
Even if you did want to use asynchronous 2-way communication because your client DID care about the result, there are different concepts:
AsyncPattern=true on the Server - you would do this in order to free up server resources, e.g. if the underlying resource (?SSRS for reporting, Mail API etc) supported asynchronous operations. But this would benefit the server, not the client.
On the client, you can always generate your service reference proxy with "Generate Asynchronous Operations" ticked - in which case your client won't block and the callback will be used when the operation is complete.
I created a RESTful service using WCF which calculates some value and then returns a response to the client.
I am expecting a lot of traffic so I am not sure whether I need to manually implement queues or it is not neccessary in order to process all client requests.
Actually I am receiving measurements from clients which have to be stored to the database - each client sends a measurement every 200 ms so if there are a multiple clients there could be a lot of requests.
And the other operation performed on received data. For example a client could send an instruction "give me the average of the last 200 measurements" so it could take some time to calculate this value and in the meantime the same request could come from another client.
I would be very thankful if anyone could give any advice on how to create a reliable service using WCF.
Thanks!
You could use the MsmqBinding and utilize the method implemented by eedsi9n. However, from what I'm gathering from this post is that you're looking for something along the lines of a pub/sub type of architecture.
This can be implemented with the WSDualHttpBinding which allows subscribers to subscribe to events. The publisher will then notify the user when the action is completed.
Therefore you could have Msmq running behind the scenes. The client subscribes to the certain events, then perhaps it publishes a message that needs to be processed. THe client sits there and does work (because its all async) and when the publisher is done working on th message it can publish an event (The event your client subscribed to) letting you know that its done. That way you don't have to implement a polling strategy.
There are pre-canned solutions for this as well. Such as NService Bus, Mass Transit, and Rhino Bus.
If you are using Web Service, Transmission Control Protocol (TCP/IP) will act as the queue to a certain degree.
TCP provides reliable, ordered
delivery of a stream of bytes from one
program on one computer to another
program on another computer.
This guarantees that if client sends packet A, B, then C, the server will received it in that order: A, B, then C. If you must reply back to the client in the same order as request, then you might need a queue.
By default maximum ASP.NET worker thread is set to 12 threads per CPU core. So on a dual core machine, you can run 24 connections at a time. Depending on how long the calculation takes and what you mean by "a lot of traffic" you could try different strategies.
The simplest one is to use serviceTimeouts and serviceThrottling and only handle what you can handle, and reject the ones you can't.
If that's not an option, increase hardware. That's the second option.
Finally you could make the service completely asynchronous. Implement two methods
string PostCalc(...) and double GetCalc(string id). PostCalc accepts the parameters, stuff them into a queue (or a database) and returns a GUID immediately (I like using string instead of Guid). The client can use the returned GUID as a claim ticket and call GetCalc(string id) every few seconds, if the calculation has not finished yet, you can return 404 for REST. Calculation must now be done by a separate process that monitors the queue.
The third option is the most complicated, but the outcome is similar to that of the first option of putting cap on incoming request.
It will depend on what you mean by "calculates some value" and "a lot of traffic". You could do some load testing and see how the #requests/second evolves with the traffic.
There's nothing WCF specific here if you are RESTful
the GET for an Average would give a URI where the answer would wait once the server finish calculating (if it is indeed a long operation)
Regarding getting the measurements - you didn't specify the freshness needed (i.e. when you get a request for an average - how fresh do you need the results to be) Also you did not specify the relative frequency of queries vs. new measurements
In any event you can (and IMHO should) use the queue (assuming measuring your performance proves it) behind the endpoint. If you change the WCF binding you might still be RESTful but will not benefit from the standard based approach of REST over HTTP