WCF服务主机关闭被打开的会话阻止,设置receiveTimeout没有帮助

本文关键字:设置 receiveTimeout 有帮助 会话 主机 服务 WCF | 更新日期: 2023-09-27 17:53:37

我需要我的WAS托管服务(PerCall, Concurrency.Multiple)优雅地关闭/回收,但任何非活动(但打开)客户端代理将阻止服务优雅地关闭。

我曾期望receiveTimout启动并抛出非活动会话,但它看起来不像那样工作。

IIS/WAS回收将调用ServiceHost。BeginClose,关闭超时设置为TimeSpan.MaxValue。

我需要允许长寿命的客户端代理(我不能真正控制)与netttcpbinding,因为吞吐量和低延迟是必须的。

我已经复制了下面的问题,并很高兴任何解决方法和帮助关于这个问题。

using System;
using System.ServiceModel;
namespace Test
{
    [ServiceContract(Name = "MyService", SessionMode = SessionMode.Allowed)]    
    public interface IHelloWorldService
    {
        [OperationContract]
        void PrintHelloWorld();
    }
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class HellowWorldService : IHelloWorldService
    {
        [OperationBehavior]
        public void PrintHelloWorld()
        {
            Console.WriteLine("Hello world!");
        }
    }
    public class ThaProgram
    {
        static void Main(string[] args)
        {
            const string ServiceAddress = "net.tcp://localhost:12345/HelloWorld";            
            var netTcpBinding = new NetTcpBinding(SecurityMode.None, false);
            netTcpBinding.ReceiveTimeout = TimeSpan.FromSeconds(3);
            var serviceHost = new ServiceHost(typeof(HellowWorldService), new Uri("net.tcp://localhost:12345"));
            serviceHost.AddServiceEndpoint(typeof(IHelloWorldService), netTcpBinding, ServiceAddress);
            serviceHost.Open();
            Console.WriteLine("Service host state: {0}", serviceHost.State);
            netTcpBinding.ReceiveTimeout = TimeSpan.FromSeconds(10);
            var channel = new ChannelFactory<IHelloWorldService>(netTcpBinding, ServiceAddress).CreateChannel();
            channel.PrintHelloWorld();
            // Uncomment to make everything work (then the session will be closed before the service enters the closing state)
            // Thread.Sleep(4000);
            // Simulate application pool shutdown
            var asyncResult = serviceHost.BeginClose(TimeSpan.MaxValue, null, null);
            Console.WriteLine("Service host state: {0}", serviceHost.State);
            serviceHost.EndClose(asyncResult);
            Console.WriteLine("Service host state: {0}", serviceHost.State);
            Console.WriteLine("Hit Enter to close the application");
            Console.ReadLine();
        }
    }
}

WCF服务主机关闭被打开的会话阻止,设置receiveTimeout没有帮助

奇怪的是TCP绑定 *WCF服务主机*不能随时切断连接,这是TCP与命名管道不同的优点。

在任何情况下,我喜欢使用的一个好模式是将所有的服务主机操作包装在一个单独的。net AppDomain中。承载服务的是这个辅助AppDomain,而不是主AppDomain。把它想象成一个沙盒。然后,当你想关闭时,你使用正常的服务主机关闭方法关闭,然后让主appdomain做一个 appdomain . unload (),这不仅保证了一个很好的方法内存清理,而且切断所有那些讨厌的客户端不能正常关闭

这样的模式在命名管道 WCF中是绝对必须的,因为客户端可以阻止服务器再次启动,就像我在以前的项目中发现的那样。(由于孤立连接)

祝一切顺利

我假定您使用的是net。Tcp,你的客户端不通过web代理连接到你的服务器。那样的话,我会让你考虑改用双工网络。解决TCP绑定问题。

使用双工绑定,可以让客户端在连接和存储回调契约的实例时调用订阅方法。在回调合约中,你可以添加一个操作,让客户端知道你想要关闭服务器。

我已经在我们的项目中为此目的有了一个双工合同,但我仍然需要实现上面的解决方案,其中我们的Windows服务中的OnStop要求客户端断开连接。不幸的是,我不知道如何在IIS托管情况下拦截BeginClose。也许使用自定义ServiceHost?