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
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 would like to be able to prioritize the outgoing data/messages from a WCF service.
Here's the basic scenario:
Client requests from server a data stream. The data stream is live, large, and potentially unending (equipment monitoring data). We'll call this HighPriorityDataStream.
Client requests additional data. We'll call this LowPriorityData.
The bandwidth is limited (think dial-up modem or satellite). It is very important that the current HigPriorityDataStream not be interrupted or delayed when a request for LowPriorityData is made.
I have a sockets-based legacy system already where this is accomplished by manually controlling the order that data is placed into the socket buffer. High-priority data is placed in the buffer, and if there's room left over, lower priority data is added to fill the rest of the buffer.
I'm trying to reengineer this process with WCF... I don't know of any out-of-the box solutions and am thinking I may need to write a custom channel behavior, but I'd like to pick the brains of the community before I go that route :)
I think there is no general out-of-the box solution. The solution is dependend on your other requirements. Do you want to control bandwith per client or per whole server (all clients)? Do you want to call low priority operation from the same proxy or do you start new proxy for new operation? Do you want to run more high priority operations at the same time? Do you want to prioritize incomming requests?
The easiest solution expects that you control bandwith per client, you are reusing same proxy for all calls, only one high priority operation can be completed at the same time and requests are processed in FIFO order. Than you just mark your service implementation with [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)] (this should be default setting for services exposed over NET.TCP). This settings will reuse the same service instance for all calls from the same client proxy but only one call will be processed at time (other will wait in queue until they are processed or time outed).
Best regards,
Ladislav
After a lot of poking around (thanks Ladislav for your thoughtful ideas), I've come to the conclusion that I'm asking the communication layer to solve a buisness-layer problem. To better state the problem, there are multiple connections and one data source. The datasource must prioritize which data it gathers from it's own data sources (live data streams and also persisted databases) and send the data back to the various clients based on their priority. To be clear, the clients have a relative priority based on their role-based identity, the data sources have a priority (prefer live data over persisted data) and individual fields within a data source have a priority order (all else being equal, field X must always be sent before field Y).
This is all firmly business-logic and the solution we adopted as a set of priority queues that autoamatically sorted the input data items based on these priority requirements and then served each request in that order.
Using techniques as hinted at in:
http://msdn.microsoft.com/en-us/library/system.servicemodel.servicecontractattribute.callbackcontract.aspx
I am implementing a ServerPush setup for my API to get realtime notifications from a server of events (no polling). Basically, the Server has a RegisterMe() and UnregisterMe() method and the client has a callback method called Announcement(string message) that, through the CallbackContract mechanisms in WCF, the server can call. This seems to work well.
Unfortunately, in this setup, if the Server were to crash or is otherwise unavailable, the Client won't know since it is only listening for messages. Silence on the line could mean no Announcements or it could mean that the server is not available.
Since my goal is to reduce polling rather than immediacy, I don't mind adding a void Ping() method on the Server alongside RegisterMe() and UnregisterMe() that merely exists to test connectivity of to the server. Periodically testing this method would, I believe, ensure that we're still connected (and also that no Announcements have been dropped by the transport, since this is TCP)
But is the Ping() method necessary or is this connectivity test otherwise available as part of WCF by default - like serverProxy.IsStillConnected() or something. As I understand it, the channel's State would only return Faulted or Closed AFTER a failed Ping(), but not instead of it.
2) From a broader perspective, is this callback approach solid? This is not for http or ajax - the number of connected clients will be few (tens of clients, max). Are there serious problems with this approach? As this seems to be a mild risk, how can I limit a slow/malicious client from blocking the server by not processing it's callback queue fast enough? Is there a kind of timeout specific to the callback that I can set without affecting other operations?
Your approach sounds reasonable, here are some links that may or may not help (they are not quite exactly related):
Detecting Client Death in WCF Duplex Contracts
http://tomasz.janczuk.org/2009/08/performance-of-http-polling-duplex.html
Having some health check built into your application protocol makes sense.
If you are worried about malicious clients, then add authorization.
The second link I shared above has a sample pub/sub server, you might be able to use this code. A couple things to watch out for -- consider pushing notifications via async calls or on a separate thread. And set the sendTimeout on the tcp binding.
HTH
I wrote a WCF application and encountered a similar problem. My server checked clients had not 'plug pulled' by periodically sending a ping to them. The actual send method (it was asynchronous being a server) had a timeout of 30 seconds. The client simply checked it received the data every 30 seconds, while the server would catch an exception if the timeout was reached.
Authorisation was required to connect to the server (by using the built-in feature of WCF that force the connecting person to call a particular method first) so from a malicious client perspective you could easily add code to check and ban their account if they do something suspicious, while disconnecting users who do not authenticate.
As the server I wrote was asynchronous, there wasn't any way to really block it. I guess that addresses your last point, as the asynchronous send method fires off the ping (and any other sending of data) and returns immediately. In the SendEnd method it would catch the timeout exception (sometimes multiple for the client) and disconnect them, without any blocking or freezing of the server.
Hope that helps.
You could use a publisher / subscriber service similar to the one suggested by Juval:
http://msdn.microsoft.com/en-us/magazine/cc163537.aspx
This would allow you to persist the subscribers if losing the server is a typical scenario. The publish method in this example also calls each subscribers on a separate thread, so a few dead subscribers will not block others...
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.
We can use polling to find out about updates from some source, for example, clients connected to a webserver. WCF provides a nifty feature in the way of Duplex contracts, in which, I can maintain a connection to a client, and make invocations on that connection at will.
Some peeps in the office were discussing the merits of both solutions, and I wanted to get feedback on when each strategy is best used.
I would use an event-based mechanism instead of polling. In WCF, you can do this easily by following the Publish-Subscribe framework that Juval Lowy provides at his website, IDesign.net.
Depends partly on how many users you have.
Say you have 1,000,000 users you will have problems maintaining that many sessions.
But if your system can respond to 1000 poll requests a second then each client can poll every 1000 seconds.
I think Shiraz nailed this one, but I wanted to say two more things.
I've had trouble with Duplex
contracts. You have to have all of
your ducks in a row with regards to
the callback channel... you have to
check it to make sure it's open,
etc. The IDesign.net stuff would be
a minimum amount of plumbing code
you'll have to include.
If it makes sense for your solution
(this is only appropriate in certain
situations), the MSMQ binding allows
a client to send data to a service
in an async manner (like Duplex),
but the service isn't "polling" for
messages... it gets notified when
one enters the queue through some
under-the-covers plumbing.
This sort of forces you to turn the
communication around (client becomes
server, server becomes client), but
if the majority of the communication
is one-way, this would provide a lot
of benefits. The other advantage
here is obviously the queued
communication - the server can be
down and not miss any messages...
it'll pick 'em up when it comes back
online.
Something to think about.