当Kestrel收到请求时,无法停止asp.net核心Windows服务

时间:2017-06-02 09:02:52

标签: c# service asp.net-core kestrel-http-server

我们正在使用.net 4.5.1上运行的asp.net核心作为Windows服务。 Kestrel用作Web服务器(Kestrel版本为1.1.2)。 它是根据Host an ASP.NET Core app in a Windows Service配置的。我们还使用在OWIN上运行的SignalR。

当两个事件同时发生时出现问题:Windows服务正在停止,Krestel收到了一些新的Web请求。如果满足这些条件,则Windows服务停止响应并挂起。

  

Windows无法停止本地计算机上的Topshelf.Host服务。   错误1061:此时服务无法接受控制消息。

配置代码:

var port = Global.Settings.Port;
var hostBuilder = new WebHostBuilder()                  
                .UseKestrel()                   
                .UseStartup<Startup>()
                .UseUrls("http://+:" + port);

if (runAsService)
 {                    
       hostBuilder.UseContentRoot(directoryPath);
       Directory.SetCurrentDirectory(directoryPath);
 }
 else
 {                    
     hostBuilder.UseContentRoot(Directory.GetCurrentDirectory());
 }

var host = hostBuilder.Build();
if (runAsService)
{                 
    host.RunAsCustomService();
}
else
{                    
      host.Run();
}

public static class WebHostServiceExtensions
{
    public static void RunAsCustomService(this IWebHost host)
    {
        var webHostService = new CustomWebHostService(host);
        ServiceBase.Run(webHostService);
    }
}
internal class CustomWebHostService : WebHostService
{
    public CustomWebHostService(IWebHost host) : base(host)
    {
    }

//...
}

进一步调查显示WebHostService.cs中部署_host时发生未处理的异常。

protected sealed override void OnStop()
{
    _stopRequestedByWindows = true;
    OnStopping();
    _host?.Dispose();
    OnStopped();
}

如下所述,它引发了一个异常“Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException:错误-4082 EBUSY资源忙或已锁定”

问题是:

有没有办法避免此类错误并阻止Windows服务挂起?例如。在_host处置或阻止OnStopping事件中的新传入连接之前停止Krestel。

Stacktrace:

  

Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException:   错误 -4082 EBUSY资源繁忙或已锁定
  在Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.Libuv.loop_close(UvLoopHandle)中   处理)   Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvLoopHandle.ReleaseHandle()   在System.Runtime.InteropServices.SafeHandle.InternalDispose()中   System.Runtime.InteropServices.SafeHandle.Dispose(布尔处理)
  在System.Runtime.InteropServices.SafeHandle.Dispose()中   Microsoft.AspNetCore.Server.Kestrel.Internal.KestrelThread.ThreadStart(对象   参数)

     

在   Microsoft.AspNetCore.Server.Kestrel.Internal.KestrelThread.d__51.MoveNext()   在System.Threading.Tasks.Task.WaitAll(Task []任务,Int32   millisecondsTimeout,CancellationToken cancellationToken)in   Microsoft.AspNetCore.Server.Kestrel.Internal.KestrelEngine.Dispose()
  在Microsoft.AspNetCore.Server.Kestrel.KestrelServer.Dispose()中   Microsoft.Extensions.DependencyInjection.ServiceProvider.Dispose()
  在Microsoft.AspNetCore.Hosting.Internal.WebHost.Dispose()

中      

Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException:   错误-4082 EBUSY资源繁忙或已锁定   Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.Libuv.loop_close(UvLoopHandle   处理)   Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvLoopHandle.ReleaseHandle()   在System.Runtime.InteropServices.SafeHandle.InternalDispose()中   System.Runtime.InteropServices.SafeHandle.Dispose(布尔处理)
  在System.Runtime.InteropServices.SafeHandle.Dispose()中   Microsoft.AspNetCore.Server.Kestrel.Internal.KestrelThread.ThreadStart(对象   参数)

     

в   Microsoft.AspNetCore.Server.Kestrel.Internal.KestrelThread.d__51.MoveNext()

1 个答案:

答案 0 :(得分:0)

在Kestrel 2.0版本中从KestrelServer.Dispose()will be fixed抛出的EBUSY异常。我认为您的服务挂起的原因是因为_host?.Dispose()正在抛出,导致OnStopped();方法无法调用OnStop()

与此同时,吞下异常以确保始终调用OnStopped();应允许停止服务。如果要重新启动服务器,请确保构建新的WebHost。