App Chain:
Running a Delphi ISAPI application under IIS 7.5/Server 2008R2 - 32 bit mode and Classic Mode pipeline.
ISAPI app (TISAPIApplication) is built with Delphi XE.
Client is a Delphi exe that generates an XML doc containing request content, including unique internal identifier generated on client side for tracking the request content, etc.
Client spawns a thread and hits the ISAPI app on webServer, passing in XML doc containing request info;
Client thread waits on server reponse and signals client when thread terminates, indicating request has been processed on server.
Problem:
User mistakenly sends a request that has potential to run for hours and/or choke up our infrastructure.
I want to enable the client app to send a message to server to abort that request (ONLY that request).
Proposed Solution:
My proposed solution is to create a dictionary on the webServer associating my client side unique identifier with a particular handle or ID for the thread that is generated on server side by the ISAPI process to handle the request. This server side ID could subsequently be used to track and abort the request if necessary when client sends request to abort, using the client side identifier.
BUT - I don't know what property/Thread-ID/handle I should be grabbing on the server side, how get to it, and how to use it to abort the request. If I can access the request handler as a Delphi thread all this should be easy enough.
Anyone know how to go about this? I'm quite certain this can be done, but I don't know exactly how to do it. Have looked around in the Delphi XE docs on TWebRequest etc, haven't found much yet.
Again, please note: I need to kill ONLY that particular request and not the whole ISAPI process - I don't want to abort any other pending requests.
From one of my mentors:
Best way to do this is to spawn a new thread in the ISAPI generated thread and store its reference in a session cache. ISAPI thread waits on this thread while it does your work - you can terminate this thread via your cached reference and ISAPI thread will terminate.
I implemented this solution and it works very well.
Related
Here is my need:
I have to displays some information from a web page.
The web browser is actually on the same machine (localhost).
I want the data to be updated dynamically by the server initiative.
Since HTTP protocol is actually a request/response protocol, I know that to get this functionality, the connection between the server and the client (which is local here) should be kept open in some way (Websocket, Server-Sent Events, etc..)
Yes, "realtime" is really a fashion trend nowadays and there are many frameworks out there to do this (meteor, etc...)
And indeed, it seems that Rails supports this functionnality too in addition to using Websockets (Server-Sent Events in Rails 4 and ActionCable in Rails 5)
So achieving this functionnality would not be a big deal, I guess...
Nevertheless what I really want is to trigger an update of the webpage (displayed here locally) from a request made by another client..
This picture will explain that better :
At the beginning, the browser connects to the (local) server (green arrows).
I guess that a thread is executed where all the session data (instance variables) are stored.
In order to use some "realtime" mechanisms, the connection remains open and therefore the thread Y is not terminated. (I guess this is how it works)
A second user is connecting (blue arrows) to the server (could be or not be the same web page) and make some actions (eg. posting a form).
Here the response to that external client does not matter. Just an HTTP OK response is fine. But a confirmation web page could also be returned.
But in anyway the thread X (and/or the connection) has no particular reason to be kept.
Ok, here is my question (BTW thank you for reading me thus far).
How can I echo this new data on the local web browser ?
I see 2 differents ways to do this :
Path A: Before terminating, the thread X passes the data (its instance variables) to the thread Y which has its connection still open. Thus the server is able to update the web browser.
Path B: Before terminating the thread X sends a request (I mean a response since it is the server) directly to the web browser using a particular socket.
Which mechanisms should I use in either method to achieve this functionnality ?
For method A, how can I exchange data between threads ?
For method B, how can I use an already opened socket ?
But which of these two methods (or another one) is actually the best way to do that?
Again thank you for reading me thus far, and sorry for my bad english.
I hope I've been clear enough to expose my need.
You are overthinking this. There is no need to think of such low-level mechanisms as threads and sockets. Most (all?) pub-sub live-update tools (ActionCable, faye, etc.) operate in terms of "channels" and "events".
So, your flow will look like this:
Client A (web browser) makes a request to your server and subscribes to events from channel "client-a-events" (or something).
Client B (the other browser) makes a request to your server with instructions to post an event to channel "client-a-events".
Pub-sub library does its magic.
Client A gets an update and updates the UI accordingly.
Check out this intro guide: Action Cable Overview.
I'm building an ASP.NET MVC site in which the clients(browser) can make API calls that take upto 30 minutes(or more..) to process. Obviously I couldn't use normal MVC Controllers to do this as a few such requests would block all my IIS worker threads leaving other faster calls blocked.
I've looked at the following two options :
ASP.NET MVC's Asynchronous controllers
PokeIn Library which allows server push via Reverse AJAX(long holding HTTP requests for older browsers) or WebSockets(from HTML5 specification for newer browsers)
Now both of it seems like a good feasible option.
Option 1 seems easiest for me to implement. With Asynchronous Controllers, my IIS worker threads wouldn't be blocked hence allowing my other faster API calls to go through seamlessly. However from the Async Controller documentation, I perceive that, it spawns of another non IIS thread which would be blocked/waiting for my long running(30~ mins) process to complete. I've read that, "If you block or sleep in a controller no matter whether it is async or not async it is very bad."
In Option 2, if my clients are using newer browsers, which supports WebSockets, this would perhaps be most performant as I do not need to have any blocking thread on the server side. When the client triggers a slow API call I'd raise an event, on the completion of which(say 30~ mins later) I'd raise another event to update all my client's browsers with the updated content.
However with PokeIn library, if part of my clients do not have WebSocket supporting browsers(older ones..), I'm not sure If they'd be hogging one of my IIS worker threads.
Is Option 2 an overkill for my requirement ?
In Option 1 is it bad to have my Async Controller wait on the slow process ?
One other disadvantage with Option 1 is that if the user Refreshes the page before the request completes, He'd no longer get the update of the job, once it completes !
Any ideas, suggestions are welcome.
Thanks
PokeIn uses same in-memory/thread pools to push the messages for websocket and ajax connections since it has internal websocket server. The delivery time certainly differs for ajax and websocket but whatever method/option you pick, you will have that difference. Besides, probably you already know but Pokein fallback to comet ajax in case a client doesn't support websocket and you don't have to deal with it.
Hope this answers your question for option 2.
I'm working on a web server built on Indy's HTTP server, and I've found that if I click on a request in the browser, and then on another one before the first one is finished processing, it can cause all sorts of problems. But I can't find any way to determine whether I'm in a canceled request or not. Each request takes place inside its own thread, so setting the thread to Terminated would be a good way to check, but that doesn't seem to be happening.
Is there any way I can get Indy to inform me that the request it's currently processing has been canceled by the browser that sent it and that it's now trying to load something different instead?
The only way a web browser can cancel an HTTP request in progress is to close its connection to the server. When that happens, TIdHTTPServer will raise an exception the next time it tries to access the disconnected socket. Just let the exception pass into TIdHTTPServer for default processing so it can terminate the calling thread and clean up the socket. This is normal behavior.
I have a SOAP server/client application written in Delphi XE working fine for some time until a user who runs it on Windows 7 x64 behind a corporate proxy/firewall. The application sends and receives TSOAPAttachment object in the request.
The Problem:
Once the first request from this user is received and processed, the server could not process any request (from any user) successfully coming after this.
The server still response to the request, but the SOAPAttachment of the request
seems corrupted after the first one from this user, that's why it couldn't process the request successfully.
After putting may debug logs to the server, I noticed the TSOAPAttachment.SourceStream in the request's parameter become inaccessible (or empty), and TSOAPAttachment.CacheFile also empty. Therefore whenever trying to use the SourceStream, it will return Access Violation error.
Further investigation found that the BorlandSoapAttachment(n) file generated in the temp folder by the first request still exist and locked (which should be deleted when a request is completed normally), and BorlandSoapAttachment(n+1) files of the following request are piling up.
The SOAP server will work again after restarting IIS or recycle the application pool.
It is quite certain that it is caused by the proxy or the user’s networks because when the same machine runs outside this networks, it will work fine.
To add more mystery to the problem, running the application on WinXP behind the same proxy have no problem AT ALL!
Any help or recommendation is very appreciated as we have stuck in this situation for some time.
Big thanks in advance.
If you are really sure that you debugged all your server logic that handles the attachments to attempt do discover any piece of code that could failed specifically on Windows 7, I would suggest:
1) Use some network sniffer Wireshark is good for this task, make two subsequent requests with the same data/parameters values, and compare the HTTP contents. This analyze should be done both in the client (to see if the data is always leaving the client machine with the same content) and also in the server, to analyze the incoming data;
2) I faced a similar situation in the past, and my attempts to really understand the problem was not well succeed. I did workaround the problem sending files as Base64 encoded strings parameters, and not using the SOAP attachments. The side affect of using Base64 its an increase of ~30% in the data size to be sent, and this could be significant if you are transferring large files.
Remember that SOAP attachments create temp files in the server, and Windows 7 has different file access rules than Windows XP. I don't know if this could explain the first call being processed ant the others not, but maybe there are something related with file access.
Maybe it is UAC (User Access Control) problem under Win 7. Try running the client in win 7 "As Administrator" and see if it is working properly.
I am trying to use jQuery's .ajax functionality to make a progress bar.
A request is submited via .ajax, which starts a long running process. Once submited another .ajax request is called on an interval which checks the progress of this process. Then a progress meter is updated using this information.
However, the progress .ajax call only returns once the long running process has completed. Its like its being blocked by the initial request.
The weird thing is this process works fine on dev but is failing on the deployment server. I am running on IIS using ASP.Net MVC.
Update: Apparently, it is browser related because it is working fine on IE 7 but is not working on IE 8. This is strange because IE 8 allows up to 6 connections on broadband where IE 7 only allows 2 requests per domain.
Update2: I think it's a local issue because it appears to be working fine on another IE 8 machine.
The server will only run one page at a time from each user. When you send the requests to get the progress status, they will be queued.
The solution is to make the page that returns the status sessionless, using EnableSessionState="false" in the #Page directive. That way it's not associated with any user, so the request isn't queued.
This of course means that you can't use session state to communicate the progress state from the thread running the process to the thread getting the status. You have to use a different way of keeping track of running processes and send some identifier along with the requests that gets the status so that you know which user it came from.
Some browsers (in particular, IE) only allows two requests to the same domain at the same time. If there are any other requests happening at the same time, then you might run into this limitation. One way around it is to have a few different aliases for the domain (some sites use "www1.example.com" and "www2.example.com", etc)
You should be able to use Firebug or Fiddler to determine how many requests are in progress, etc.
Create an Asynchronus handler (IHttpAsyncHandler) for your second ajax request.
use any parameter required via the .ashx querystring in order to process what you want because the HttpContext won't have what you'll need. You barely will have access to the Application object.
Behind the scenes ASP.NET will create for you a thread from the CLR pool, not the application pool, so You'll have an extra performance gain with IHttpAsyncHandler