How does IIS handles multiple simultaneous requests to a web service using the same session id when that web service relies on sessions?
If the first web service call has not finished processing, does IIS queue the second web service call temporarily until the first web service call has finished (since they both rely on the same session data).
Or does IIS allow both requests to go forward and any changes made to the session store by the first request immediately affect the second web service call in process even thought that may cause unexpected results.
I believe it is using the first option by queuing the second call until the first is completed due to session reader\writer locks but I have not been able to locate a definitive answer.
Note: In this case the web service requests are generated from the client browser asynchronously.
Yes, like anything else that's using session state, the session state module is going to block the request from going any further down the pipeline (i.e. executing your ASMX web method) until it can aquire the lock to the session. Session state is the enemy of concurrency, avoid it at all costs.
Related
I have a web method in an ASP.NET site that could run long and consume a lot of CPU capacity. It is also possible that, before a request is returned, the user could fire a new request with other or more parameters from the site. On the client side a do an abort:
if (xhrConfigurate != null) {
xhrConfigurate.abort();
}
Of course, abort will not stop the calculations on the server. I tought, this is ok, the server will do what it have to do, but will not return the results of the old requests. But it seems that in some cases, the server has troubles to handle all requests in a timely matter.
That is why I also want to kill the old requests when a user launches a new one. I have found some solutions with scriptmanager, but would like to avoid using that.
As the webmethod itself is a asynchronous thread, can't I get an instance of this thread, store it in some dictionary where I can abort the old not finished requests for a user and remove a request when it is finished?
<WebMethod> Public Shared Function myRequest(ByVal params As String) As String
'Get the dictionary with requests
'Test the dictionary on old unfinsihed request for the user, if there is one: abort
'Add this request to the dictionary
'Do work...
'If work finsihed: remove this request from dictionary
Return result
End Sub
If I understand correctly, you want to have some global variable dictionary with requests queue, so that any web method execution would share same dictionary?
Using global variable is tricky thing, IIS application pool may restart anytime. Somewhere I read, it's recycling automatically every 24 or 29 hours on IIS. So global variable values might be lost.
Thread related to the problem:
What exactly is Appdomain recycling
I have ASP WebApi service, and I have similar long running tasks. I host ASP application in console app (host) (no IIS!), and I use ObservableCollection variable to store requests in AppDomain.
Then each requests thread can access that collection safely (if I am not mistaken).
In general, it is a bad idea to run a long-running process inside of ASP.NET. Instead, you should create a separate server process, and your ASP.NET code should queue a request to that process.
Your server could return a unique value back to ASP.NET, which could then send that value back to the web page. When the user makes a request, you would pass that value to ASP.NET, which would pass it to the service. The service could determine whether there is already a request running with that unique value and, if there is, the service could abort that thread.
This is ASP.NET ASMX Web Service / .NET Framework 4.0.
In web service, I want to execute one method on another thread something like “Fire and Forget” so that Web Service returns some value in response immediately to web site. That method on another thread could take 10 minutes after Web Service returns response immediately to Web site. Also, I do not need return value of that method.
I have tested this scenario using ThreadPool.QueueUserWorkItem and it seems that thread started using ThreadPool will still keep executing even after Web Service returns response back to Web site. Am I correct here? Also is there a better way to achieve this?
The problem is that every now and then, ASP.NET will recycle the app pool. Because it doesn't know about your background task, it will not be considered and will be aborted when the AppDomain is disposed.
Most of the time, the work will complete, but if you run for long enough, you will encounter this scenario.
There are two solutions:
1) The "proper" way is to write a Windows Service that runs outside ASP.NET. You can send instructions to the Service over WCF.
2) The "quick and dirty" way is to write a hidden web service in your ASP.NET site that is never called by users. Your app starts an asynchronous request to the hidden service and then returns its own result to the user, without waiting.
ASP.NET does not know that the request to the hidden service came from inside your app - it just treats it as another request. Because ASP.NET knows about this request, it will not abort it when it recycles.
I have an ASP.NET Webform which currently calls a Java WebService. The ASP.NET Webform is created/maintained inhouse, whereas the Java WS is a package solution where we only have a WS interface to the application.
The problem is, that the Java WS is sometimes slow to respond due to system load etc. and there is nothing I can do about this. So currently at the moment there is a long delay on the ASP.NET Webform sometimes if the Java-WS is slow to respond, sometimes causing ASP.NET to reach its timeout value and throw the connection.
I need to ensure data connectivity between these two applications, which I can do by increasing the timeout value, but I cannot have the ASP.NET form wait longer than a couple of seconds.
This is where the idea of a queuing system comes into place.
My idea is, to have the ASP.NET form build the soap request and then queue it in a local queue, where then a Daemon runs and fires off the requests at the Java-WS.
Before I start building something from scratch I need a couple of pointers.
Is my solution viable ?
Are there any libraries etc already out there that I can achieve this functionality with ?
Is there a better way of achieving what i am looking for ?
You can create a WindowsService hosting a WCF service.
Your web app can them call the WCF methods of your Windows Service.
Your windows service can call the java web service methods asynchronously, using the
begin/End pattern
Your windows service can even store the answers of the java web service, and expose them through another WCF methods. For example you could have this methods in your WCF service:
1) a method that allows to call inderectly a java web service and returnd an identifier for this call
2) another method that returns the java web service call result by presenting the identifier of the call
You can even use AJAX to call the WCF methods of your Windows Service.
You have two separate problems:
Your web form needs to learn to send a request to a service and later poll to get the results of that service. You can do this by writing a simple intermediate service (in WCF, please) which would have two operations: one to call the Java service asynchronously, and the other to find out whether the async call has completed, and return the results if it has.
You may need to persistently queue up requests to the Java service. The easiest way to do this, if performance isn't a top concern (and it seems not to be), is to break the intermediate service in #1 into two: one half calls the other half using a WCF MSMQ binding. This will transparently use MSMQ as a transport, causing queued requests to stay in the queue until they are pulled out by the second half. The second half would be written as a Windows service so that it comes up on system boot and starts emptying the queue.
you could use MSMQ for queuing up the requests from you client.
Bear in mind that MSMQ doesn't handle anything for you - it's just a transport.
All it does is take MSMQ messages and deliver them to MSMQ queues.
The creation of the original messages and the processing of the delivered messages is all handled in your own code on the sending and receiving machines: the destination machine would have to have MSMQ installed plus a custom service running to pick them up and process them
Anyway there is a librays for interop with MSQM using JAVA : http://msmqjava.codeplex.com/
Another way could be you can create a queue on one of your windows box and then create a service that pick up the messages form the Queue and foreward them to the Java service
I have created a ASMX Web Service which does some Active Directory stuff behind the scene.
As I wish to retain certain information within Web Services under user session, I have decided to put [WebMethod(EnableSession = true)] and start using Session variables.
However, when I turn that option on, the return time from app -> web service -> app has became ridiculously long. (about a minute or more).
If I remove [WebMethod(EnableSession = true)], it is fairly fast.
Anyone know what is going on?
Possible reasons:
Session state is stored out of process (state server/ SQL server) and getting/storing it taking a long time
You are making multiple concurrent requests (including service requests) under the same session. ASP.NET ensures that only one session-full (session read/write) request execute at a time and hence, multiple concurrent requests would queue up.
EDIT :
For #2, obvious solution is to avoid session state use - for example, can you put the relevant information into another store such as cache or database (expensive).
If you are only reading session state in web service then you may take advantage of read-only session state (see IReadOnlySessionState). Read-only session state allows concurrent read-only requests - read/write request will still block all other requests. Now, EnableSession from WebMethod attribute does not support this - it either provides no session or read/write session. So one of the workaround can be to implement your own handler implementing IReadOnlySessionState and then route asmx request to thi handler using a http-module and then switch the handler to default one later. Because your handler requires read-only session state, you will have the read-only session state - see this forum post where such http-module that switches the handler has been given.
What is the difference between Web Services Asynchronous Call and Asynchronous Task's.
We are working an a ASP.NET application that requires to make a call to a Web Service Method that will process thousand rows of data. This process usually takes between 2 to 3 minutes (maybe more maybe less it depends of the amount of Data). So we run all the time in Timeout's on that specific page.
So we decided to go in rout of calling this Web Service Method Asynchronously, but we had a conflict caused by HTTP handler of one of the UI component's that we are using. Well lucky on that case we could remove the page from the httphandler directives.
So far no issues, but here it comes the question, a coworker find out that we can use instead of Asynchronous Webs Services Call, wrap a Synchronous call in a Asynchronous Task in the ASP.NET page and be able to keep the directives to the component, and execute the Web Service Method with out getting a Timeout.
So now my concern is what kind of issues we can find using Asynchronous Task's instead of an Asynchronous Call.
Thank you in advance.
Web services should not be used in this manner by the way. There's a reason HTTP timeouts are so low. You should have the Web service trigger the task either by setting a flag in the DB that an actual service picks up on or the web service should spawn a process.
If I understand your scenario, there should be no issues. In both cases, your page is asynchronous. In both cases, you don't wait for the service to complete - you give up the request thread while the service is running. In both cases, your page takes the same amount of time to execute as it would if you had called the service synchronously.