事情的经过是这个样子的:
First, the property "Keep-Alive" of HttpConnection(1.1 version) is the evil root of this disaster.
通过System.Net.Tracing配置,我们可以看到这样的Log:
The underlying connection was closed: A connection that was expected to be kept alive was closed by the server.
经过调查发现,Keep-Alive is enabled,不过timeout 在server端的设置只有5s,而client端用的默认的值(100s),两端的设置不同。那么这个时候就会出现:用户在5s内不发出任何请求,server端就会把连接关掉,但是对于100s的client端来说,连接还保持着,所以不会重新create一个连接,而是使用原来的连接。这时候,server端就会传回来The request was canceled.
solutions.
1. Set Keep-Alive off.
Override method GetWebRequest of System.Web.Services.Protocols.SoapHttpClientProtocol in our Reference.cs.
protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)base.GetWebRequest(uri);
webRequest.KeepAlive = false;
return webRequest;
}
但是这种方案的性能不好,因为每次请求结束之后都要关掉连接。再请求的时候还要重新create 一个ServicePoint。
2. Adjust Keep-Alive Timeout Setting on Server-side and MaxServicePointIdleTime on Client-side.
Here is the guildeline of this solution: make sure the idle timeout on the client side is less than that on the server side
E.g. Keep-Alive Timeout setting on our server is 5s, and then we could modify the MaxServicePointIdleTime in main method of ShellApplication.cs.
Here is the example code:
namespace COM.OOCL.TMS.Shell
{
public class ShellApplication : FormShellApplication<ShellWorkItem, ShellForm>
{
……
[STAThread]
static void Main()
{
//AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomainUnhandledException);
//Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("zh-CN");
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
static void Main()
{
//AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomainUnhandledException);
//Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("zh-CN");
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
//The cilent idle time is 4s, which is less than that on server side(5s).
System.Net.ServicePointManager.MaxServicePointIdleTime = 4000;
System.Net.ServicePointManager.MaxServicePointIdleTime = 4000;
Application.SetCompatibleTextRenderingDefault(false);
…...
}
参考:
http://support.microsoft.com/default.aspx?scid=kb;EN-US;915599
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetservicepointmanagerclassmaxservicepointidletimetopic.asp
http://www.io.com/~maus/HttpKeepAlive.html
…...
}
参考:
http://support.microsoft.com/default.aspx?scid=kb;EN-US;915599
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetservicepointmanagerclassmaxservicepointidletimetopic.asp
http://www.io.com/~maus/HttpKeepAlive.html


