0

In order to overcome the (apparent) 4 minute idle connection timeout on the Azure load balancer, it seems necessary to send some data down the pipe to the client every now and again to keep the connection from being regarded as idle.

Our controller is set up as an AsyncController, and it fires several different asynchronous methods on other objects, all of which are set up to use IO Completion Ports. Thus, we return from our method immediately, and when the completion packet is processed, IIS hooks back up to the original request so that we can render our View.

Is there any way to periodically send a few bytes down the wire in this case? In a "classic" situation, we could have executed the method and then just spun while we waited, sending data every few seconds until the asynchronous method was complete. But, in this situation, the IIS thread is freed to go do other business, and we hook back up to it in our completion callback. What to do? Is this possible?

Pittsburgh DBA
  • 6,672
  • 2
  • 39
  • 68

1 Answers1

0

While your particular case concerns Windows Azure specific (the 4 minute timeout of LBs), the question is pure IIS / ASP.NET workwise. Anyway, I don't think it is possible to send "ping-backs" to the client while in AsyncController/AsyncPage. This is the whole idea of the AsyncPages/Controllers. The IIS leaves the socket aside having the thread serving other requests. And gets back only when you got the OutstandingOperations to zero with AsyncManager.OutstandingOperations.Decrement(); Only then the control is given back to send final response to the client. And once you are the point of sending response, there is no turning back.

I would rather argue for the architectural approach of why you thing someone would wait 4 minutes to get a response (even with a good animated "please wait")? A lot of things may happen during this time. From browser crash, through internet disruption to total power loss/disruption at client. If you are doing real Azure, why not just send tasks for a Worker Role via a Queue (Azure Storage Queues or Service Bus Queues). The other option that stays in front of you for so long running tasks is to use SingalR and fully AJAXed solution. Where you communicate via SignalR the status of the long running operation.

UPDATE 1 due to comments

In addition to the approach suggested by @knightpfhor this can be also achieved with a Queues. Requestor creates a task with some Unique ID and sends it to "Task submission queue". Then "listens" (or polls at regular/irregular intervals) a "Task completion" queue for a message with given Task ID.

In any way I don't see a reason for keeping client connected for the whole duration of the long running task. There are number of ways to decouple such communication.

astaykov
  • 30,768
  • 3
  • 70
  • 86
  • Good question. This is for server to server B2B scenario, running long processes in the cloud. The callers can only perform standard request/response so they have to wait. – Pittsburgh DBA Oct 04 '12 at 19:51
  • 1
    Could the servers send an initial request and then poll for progress? If so this might be useful: http://stackoverflow.com/questions/6184752/set-timeout-for-controller-action/6192680#6192680 – knightpfhor Oct 04 '12 at 20:06
  • @knightpfhor Thank you for replying. No, as I mentioned in my comment, these servers are only capable of basic request/response. They cannot poll, otherwise I would respond immediately and let them poll for a result, or I would accept a callback URL which I would invoke later with the response. – Pittsburgh DBA Oct 04 '12 at 22:59
  • @astaykov I agree with the philosophical part of your update. However, reality intrudes, and these paying clients have to stay connected for a long time. Their platforms do not support disconnect/poll. They only support request/response, and they are cutting the checks. These are not browser apps, they are server-to-server business-to-business transactions, and we must find a solution for this. – Pittsburgh DBA Oct 08 '12 at 14:12
  • make your long running transactions run faster. As I said, there is no way (with AsyncController) to "ping-back" the connected client. At the end, if you really insist to have such an option, you have to do the low-level TCP/IP programming on your own. I still wonder what happens to that paying B2B customer if the connectivity between your servers and their servers drops, while you still complete the long-running op successfully? – astaykov Oct 08 '12 at 20:44