tags:

views:

23

answers:

3

I have a request to my own service that takes 15 seconds for the service to complete. Should not be a problem right? We actually have a service-side timer so that it will take at most 15 seconds to complete. However, the client is seeing "the connection was forcibly closed " and is automatically (within in the System.Net layer--I have seen it by turning on the diagnostics) retrying the GET request twice.

Oh, BTW, this is a non-SOAP situation (WCF 4 REST Service) so there is none of that SOAP stuff in the middle. Also, my client is a program, not a browser.

If I shrink the time down to 5 seconds (which I can do artificially), the retries stop but I am at a loss for explaining how the connection should be dropped so quickly. The HttpWebRequest.KeepAlive flag is, by default, true and is not being modified so the connection should be kept open.

The timing of the retries is interesting. They come at the the end of whatever timeout we choose (e.g. 10, 15 seconds or whatever) so the client side seems to be reacting only after getting the first response.

Another thing: There is no indication of a problem on the service side. It works just fine but sees a surprising (to me) couple of retry of the requests from the client.

I have Googled this issue and come up empty. The standard for keep-alive is over 100 seconds AFAIK so I am still puzzled why the client is acting the way it is--and the behavior is within the System.Net layer so I cannot step through it.

Any help here would be very much appreciated!

== Tevya ==

A: 

Change your service so it sends a timeout indication to the client before closing the connection.

Peter G.
Please elaborate on your solution. The service does not close the connection explicitly. Even so, I do not know how one would send a timeout indication to the client in the ASP.NET environment. Thirdly, the request is not timing out. The request is only lasting 15 seconds. The client should be able to wait that long.
Tevya
Then, the service seems to close the connection implicitly. I'm sorry that I am not versed in your infrastructure layers to explain how that happens.
Peter G.
A: 

Sounds like a piece of hardware (router, firewall, load balancer?) is sending a RST because of some configuration choice.

matt-dot-net
A: 

I found the answer and it was almost totally unrelated to the timeout. Rather, the problem is related to the use of custom serialization of response data. The respose data structures have some dynamically appearing types and thus cannot be serialized by the normal ASP.NET mechanisms.

To solve that problem, we create an XmlObjectSerializer object and then pass it plus the objects to serialize to System.ServiceModel.Channels.Message.CreateMessage(). Here two things went wrong:

  1. An unexpected type was added to the message [how and why I will not go into here] which caused the serialization to fail and
  2. It turns out that the CreateMessage() method does not immediately serialize the contents but defers the serialization until sometime later (probably just-in-time).

The two facts together caused an uncatchable serialization failure on the server side because the actual attempt to serialize the objects did not occur until the user-written service code had returned control to the WCF infrastructure.

Now why did it look like a timeout? Well, it turns out that not all the objects being returned had the unexpected object type in them. In particular, the first N objects did not. So, when the time limit was lengthened beyond 5 seconds, the N+1th object did reference the unknown type and was included in the download which broke the serialization. Later testing confirmed that the failure could happen even when only one object was being passed back.

The solution was to pre-process the objects so that no unexpected types are referenced. Then all goes well.

== Tevya ==

Tevya