背景
我在这里提供的服务如下:
在回收appdomain后,将重新使用相同的端口。这样,客户端仍然知道要连接到哪个端口。 WCF服务器是基于TCP的。
回收
在回收发生之前,appdomain会进行一些清理。最重要的是,WCF服务主机已关闭,我希望释放TCP-IP端口。更详细:
this.serviceHost.Close();
this.serviceHost = null;
// Some other cleanup
GC.Collect(GC.MaxGeneration);
GC.WaitForFullGCComplete();
GC.WaitForPendingFinalizers();
清理后,appdomain停止,并在第二次启动后再次启动。停止应用程序域非常简单:
try
{
System.AppDomain.Unload(this.serviceDomain);
this.serviceDomain = null;
}
catch (CannotUnloadAppDomainException err)
{
Console.WriteLine("Cannot unload app domain (attempt #{1}): {0}", err.Message, i + 1);
Thread.Sleep(TimeSpan.FromSeconds(1.0));
}
catch (AppDomainUnloadedException)
{
this.serviceDomain = null;
}
问题
大多数时候一切正常。但是,每隔几周一次,回收工作正常,但WCF服务器无法访问。错误是:
System.ServiceModel.ProtocolException: You have tried to create a channel to a service that
does not support .NET Framing. It is possible that you are encountering an HTTP endpoint.
---> System.IO.InvalidDataException: Expected record type 'PreambleAck', found '72'.
我发现最奇怪的是WCF服务器似乎正确设置了所有内容。因此,当我调用serviceHost.Open();
时,不会抛出任何异常,这有点像套接字被另一个进程劫持时的预期。
我正在寻找的是可能的根本原因以及我可以测试以解决此问题的事情。
我尝试过的事情
问题出现在多台计算机上,每隔几周就会发生一次。重新启动整个过程可以解决此问题。
netstat -aonb
是否该端口被其他进程劫持。 (似乎不太可能,但是又一次......)Netstat报告该端口被PID 4(系统)使用。当服务器按预期工作时,它会报告相同的事情。