Topshelfを使用してWCFサービスをWindowsサービスとしてホストしています。コンソールで実行している場合でも、Ctrl-Cを送信してからシャットダウンするまでに非常に長い時間がかかります。これは、サービスとして実行している場合に反映されます。私のローカルマシンでは、svcHost.Close(new TimeSpan(0))を呼び出すのに1ミリ秒かかりますが、Topshelfが呼び出すStopメソッドの終了からコードがRunner.Host()メソッドから外れるまでの間に10240ミリ秒かかります。これは素晴らしいことではありませんが、私が試した実稼働サーバーでは、2番目の値は70年代です。これは、サービスがジャンクであると判断する前に、Windowsがサービスを提供する30秒以上の方法です。
これが私のTopshelfコードとサービスコードです。例外が発生していないことを確認したため、Log4Netロギングと例外処理の両方を大幅に削除しました。
public class Service
{
private ServiceHost svcHost;
public void Start()
{
string bindUri = "net.tcp://MyMachineName:10000";
svcHost = new ServiceHost(typeof(MyServiceClass));
svcHost.AddServiceEndpoint(typeof(IMyService), new NetTcpBinding("tcp"), bindUri);
svcHost.Description.Behaviors.Add(new LoggerBehavior());
svcHost.Open();
}
public void Stop()
{
svcHost.Close(new TimeSpan(0));
svcHost = null;
}
}
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
var cfg = RunnerConfigurator.New(c =>
{
c.ConfigureService<Service>(s =>
{
s.Named("MyServiceName");
s.HowToBuildService(x => new Service());
s.WhenStarted(service => service.Start());
s.WhenStopped(service =>
{
sw.Start();
service.Stop();
sw.Stop();
Console.WriteLine("Stop Time: {0}ms", sw.ElapsedMilliseconds); // usually 1-2ms
sw.Reset();
sw.Start();
});
});
c.RunAsLocalSystem();
c.SetDescription("Runs MyServiceName.");
c.SetDisplayName("MyServiceName");
c.SetServiceName("MyServiceName");
});
Runner.Host(cfg, args);
sw.Stop();
// ~10 seconds on my machine, ~70s on a production server!
Console.WriteLine("Finish Time: {0}ms", sw.ElapsedMilliseconds);
}
}
10秒強と70秒強は「デフォルト」になりすぎるように思われるので、タイムアウトをできるだけ低く設定するために高低を検索しましたが、どれもうまくいかないようです。これが私のapp.configコードです。
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="tcp"
maxReceivedMessageSize="52428800"
transferMode="Buffered"
openTimeout="0:00:01"
sendTimeout="0:00:01"
receiveTimeout="0:00:01"
closeTimeout="0:00:01">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling maxConcurrentCalls="100" maxConcurrentInstances="100" maxConcurrentSessions="100" />
<serviceTimeouts transactionTimeout="0:00:01" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="MyApp.MyServiceClass" behaviorConfiguration="MyServiceBehavior">
<host>
<timeouts openTimeout="0:00:01" closeTimeout="0:00:01" />
</host>
</service>
</services>
</system.serviceModel>
では、WCFをより速くシャットダウンするために何ができるでしょうか。