I have a WCF service with public REST and SOAP endpoints that has a single post method. Currently the app processes as follows
Object Posted to service method
Service method passes data to storage queue then sends an XML response.
Second worker role checks queue, does some processing and depending on processing, adds record to DB or rejects it.
My problem currently is that the WCF method responds before a decision is made to accept or reject the message. There is a lot of processing, and various worker roles are used after the WCF message is received depending on customer settings. I would like to be able to make the accept/reject decision and then respond with relevant data. I am wondering how to do this.
I could do an asynchronous Service method, but then all code would need to go into the WCF role or callable library which isn't ideal. Is there a way to not to the async End method until there is a response from another worker role (a message is in the queue)? I realize I could just do a thread.sleep and check the queue periodically, but then I would have to add the original request data to the queue and I really don't think that's the correct way to do things. I Googled this and couldn't find a concrete, non-hackish method.
Let me know if code samples would help, but (I think) it's pretty straightforward.
Related
We're writing a WCF service which will have to manage external client petitions, on those petitions we will:
Connect to another external service (not under our control) and validate a signature to ensure the identity of the caller.
Make several operations on our environment.
Finally, if everything is ok, call to another external service (again not under our control) and obtain a registry number to send to the client as a response.
From my point of view, the external services calls add too much entropy to allow all process in only one operation, there are lots of possible scenarios out of our reach that can finish with a timeout on the final client.
IMHO we should try to write different operations to manage each of the different parts (generating a secure token to carry authentication during 2nd and 3rd steps) so we can avoid an scenario where all the processes works fine but takes too much time and the client stops waiting for the response, generating a timeout.
My opinion is not shared for other members of the team, who wants to do all in a single operation.
Is there a best practice for this type of scenarios?
Will be better to use different operations or won't it have impact at all?
You can leverage of callback contract. Create oneway operation and let client invoke service and order all work to be done. Within method save client's reference and once all the long-running work is done, check if client's reference is not null so as to make sure client has not been closed. If not then invoce callback operation specified in callback contract. The pros of such as way out is that client does not keep waiting for the result but he is informed when result is obtained and ready to be provided. I refer you to this post.
I have a website where I need to take a bit of data from the user, make an ajax call to a .net webservice, and then the webservice does some work for about 5-10 minutes.
I naturally dont want the user to have to sit there that whole time, so I have made it an asynchronous ajax call to the webservice, and after the call has been sent, I redirect the user to a "you are done!" page.
What I want to happen is for the webservice to keep running to finish--and not abort--after it receives the information from the user.
From my testing, this is more or less what happens, but now I'm finding that this might be limited by time? I.e. if the webservice runs past a certain amount of time, it will abort if the user isnt still connected.
I might be off here in this assessment, but this is what I THINK is going on from my testing.
So my question is whether with .net web services, if this is indeed what happens? Does it get aborted after some time if the user isnt still on the other end? Is there any way to disable this abort?
Thanks in advance!
when you invoke a web service, it will always finish its work, even if user leaves the page that invoked it.
Of course webservices have their own configuration and one of them sets timeout.
If you're creating a WCF service (SOAP Service) you can set it in its contract (changing binding properties), if you're creating a service with WebApi or MVC (REST/Http Service) then you can either add to its config file or programmatically set in its controller as it follows.
HttpContext.Server.ScriptTimeout = 3600; //Number of seconds
That can be a reason causing webservice to interrupt its work but it is not related to what happens on client side.
Have a nice day,
Alberto
Whilst I agree that the answer here is technically correct, I just
wanted to post a more robust alternative approach that avoids some of
the pitfalls possible with your current approach such as
Web Server being bounced during the long-running processing of request
Web Server App pool being recycled during processing
Web server running out of threads due to too many long-running requests and not being able to process any more requests
I would recommend you take a thoroughly ansynchronous approach and use
Message Queues (MSMQ for example) with a trigger on the queue that
will execute the work.
The process would be:
Your page makes Ajax call to the Webservice
Webservice writes a message into the Queue and returns right away. The message contains details of what work needs to be carried out.
User continues on your site as usual, or goes home, etc.
A trigger on the Queue is watching for messages and when a message
arrives in the queue, it activates a process which:
Reads the message
Performs the necessary work
Updates any back-end storage, etc, with the results of the work
This is much more robust because it totaly decouples the Web service from any long-running work and means that if the user makes a request and the web server goes down a moment later (for whatever reason) then the work will still be queued up when the server comes back online, etc.
You can read more about it here (MSMQ is the MS Message Queue tech; there are many others!)
Just my 2c
I'd like to know which is the best way to create a background task in the server, to send e-mails.
The idea is that a person bids an item, and this automatically sends a mail to the task responsible which it sends the mail to the correspondent person, but how can I do this without affecting the website functionality or making it slow.
I've read some things about async tasks but not sure if this is the solution to my problem.
You can create asynchronous background threads, look at the usage of
the .NET framework Task class if you are using .NET 4.x, in prior versions
you have to look at Thread or ThreadStart.
But be careful with accessing data, to prevent the main thread and your email
thread from getting into problems, you also need to look at locking resources
with the "lock" statement.
This is good, if you need to send many emails in one go and this should be done
asynchronously, which means "the user should not have to wait for it".
In the web, this is also the best way to do such things in a thread, as you
could get a request time out if it takes too long.
But of course, at the end of the thread, you should somehow create a report
and also send that to the executing user, so that he knows that mailing has finished
or if any errors occured.
We solved this in our company by creating a web service which is responsible
for shipping emails to the SMTP service and log them, including content and
status of email sending.
Our apllications build up the emails in the format defined from our web service
and they are responsible for staus report for the end user.
Of course by doing this, you will still need to have a layer which builds up
the email you want to send and the forward it to the mail service, and this
maybe still needs to be done async. so only the relaying to SMTP itself would
be separated from your application like this.
But if you have an application which needs to do mass mailing or something like that
and you want to separate it from your "normal" tool, (e.g. for separating processes
and process load) then simply create a separate service which "knows" the domain of your main application.
By doing this, you would only have to trigger the mailing service by sending the according information from the main application to the mailing service.
But again, maybe you need to build up a background thread which collects and sends the
information required to that service.
You could create this service in many ways, using WCF for example, as background windows service with message enqueing, or a HTTP based service with a rest API, etc. etc.
You did not give that much information about what you need to do, but maybe this will
point you to the right direction.
I have a c# WCF web service which is a server and I do have 2 clients one is java client and another is c++ client. I want both the clients to run at the same time. The scenario I have and am unable to figure it out is:
My java client will be making a call to the WCF web service and the processing time might take around 10 mins, meanwhile I want my c++ client to make a call to the web service and the get the response back. But right now I am just able to make a call to web service using c++ client when the java client request is being processed. I am not getting the response back for c++ client request until java client request is completed.
Can any one please suggest me how to make this work parallel. Thanks in advance.
Any "normal" WCF service can most definitely handle more than one client request at any given time.
It all depends on your settings for InstanceContextMode:
PerSession means, each session gets a copy of the service class to handle a number of requests (from that same client)
PerCall means, each request gets a fresh copy of the service class to handle the request (and it's disposed again after handling the call)
Single means, you have a singleton - just one copy of your service class.
If you have a singleton - you need to ask yourself: why? By default, PerCall is the recommended setting, and that should easily support quite a few requests at once.
See Understanding Instance Context Mode for a more thorough explanation.
Use
[ServiceBehavior( ConcurrencyMode = ConcurrencyMode.Multiple )]
attribute over your service class. More on this for example here:
http://www.codeproject.com/Articles/89858/WCF-Concurrency-Single-Multiple-and-Reentrant-and
This is peripheral to your question but have you considered asynchronous callbacks from the method that takes 10+ minutes to return, and then having the process run in a separate thread? It's not really good practice to have a service call waiting 10 minutes synchronously, and might solve your problem, although the service should allow for multiple callers at once anyway (our WCF service takes thousands of simultaneous requests).
When you call a WCF you have a choice in either calling it synchronously or asynchronously. A synchronous call waits for the response to send back to the caller in the same operation. In the caller it would look like "myresult = svc.DoSomething()". With an asynchronous call, the caller gives the service a function to call when it completes but does not wait for the response. The caller doesn't block while waiting for the response and goes about its business.
Your callback will take DoSomethingCompletedEventArgs:
void myCallback(object sender, DoSomethingCompletedEventArgs e)
{
var myResult = e.Result;
//then use the result however you would have before.
}
You register the callback function like an event handler:
svc.DoSomethingCompleted+=myCallback;
then
svc.DoSomethingAsync(). Note there is no returned value in that statement; The service would execute myCallBack when it completes and pass the result. (All WCF calls from Silverlight have to be asynchronous but for other clients this restriction isn't there).
Here's a codeproject article that demonstrates a slightly different way in detail.
http://www.codeproject.com/Articles/91528/How-to-Call-WCF-Services-Synchronously-and-Asynchr
This keeps the client from blocking during the 10+ minute process but doesn't really change the way the service itself functions.
Now the second part of what I was mentioning was firing off the 10+ minute process in a separate thread from inside the service. The service methods themselves should be very thin and just be calling functionality in other libraries. Functions that are going to take a long time should ideally be called in their own threads (say a backgroundworker, for which you register on the service side a callback when it completes) and have some sort of persistent system to keep track of their progress and any results that need to go back to the client. If it were me I would register the request for the process in a db and then update that db with its completion. The client would then periodically initiate a simple poll to see if the process was completed and get any results. You might be able to set up duplex binding to get notified when the process completes automatically but to be honest it's been a few years since I've done any duplex binding so I don't remember exactly how it works.
These topics are really too big for me to go into depth here. I would suggest researching multithreaded operations with the BackgroundWorker.
I have a quick simply question about requests in WCF. Does WCF automatically queue requests to a service(the service being a singleton) when multiple users request the same process, ie lets say I have a function that takes a while to complete, and two users make a call to this function, does WCF automatically queue the requests so that when the first request is finished it then starts processing the next?
~Just Wondering
The service behavior attribute on the contract defines how sessions, instances and concurrency are handled. See http://msdn.microsoft.com/en-us/library/ms731193.aspx for more details.
Basically you can configure it (1) handle one request at a time or (2) multiple requests at the same time.