WAS がホストするサービス (PerCall、Concurrency.Multiple) を正常にシャットダウン/リサイクルする必要がありますが、非アクティブな (ただし開いている) クライアント プロキシはサービスの正常なシャットダウンをブロックします。
receiveTimout が起動して非アクティブなセッションを破棄することを期待していましたが、そのようには機能しないようです。
IIS/WAS リサイクルは、終了タイムアウトを TimeSpan.MaxValue に設定して ServiceHost.BeginClose を呼び出します。
スループットと低レイテンシーが必須であるため、netTcpBinding を使用して長期間有効なクライアント プロキシ (実際には制御できません) を許可する必要があります。
以下の問題を再現しました。この問題に関する回避策とヘルプがあれば幸いです。
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();
}
}
}