简体   繁体   中英

WCF service hosted in Topshelf takes long time to shut down

I'm using Topshelf to host a WCF Service as a Windows Service. Even when just running on the console, it takes an exceptionally long time to shut down after I send it a Ctrl-C, and this is mirrored when running as a service. On my local machine, it takes 1ms to call svcHost.Close(new TimeSpan(0)), but 10240ms between the end of my Stop method that Topshelf calls and after the code falls out of the Runner.Host() method. This isn't great, but on a production server I tried, the second value is 70s. That's WAY more than the 30 seconds Windows will give a service before it decides the service is a piece of junk.

Here's my Topshelf code and service code. I've stripped both down a lot to remove the Log4Net logging and exception handling, because I've verified exceptions aren't occurring.

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);
    }
}

Just over 10 seconds and just over 70 seconds seems far too "defaulty" so I've searched high and low for timeouts to set as low as possible but none of them seems to do any good. Here's my app.config code.

<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>

So what can I do to get WCF to shut down faster?

It does appear that Topshelf is hanging when attempting to shutdown in 2.1.0.0. This is something we'll have to look into.

Additionally, you can always download the latest Topshelf develop branch binaries from http://teamcity.codebetter.com/ . Login as guest and find the Masstransit project, the build is under that section.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM