.NET Core 3.1和WorkerServices构建Windows服务

  • 2020 年 2 月 24 日
  • 笔记

介绍

ASP.NET Core 3增加了一个非常有意思的功能Worker Service.他是一个ASP.NET Core模板,他允许我们创建托管长期的运行的后台服务,这些服务具体实现IHostedService接口的后台任务逻辑,他被成为”托管服务”.同时他们可以部署到windows中Windows服务,以及Linux守护程序.

创建一个托管服务

我们通过命令行界面中的dotnet new 命令。通过如下代码创建一个名为customWorker的WorkerService的应用。

dotnet new worker -o customWorker

Program.cs:

using System;  using System.Collections.Generic;  using System.Linq;  using System.Threading.Tasks;  using Microsoft.Extensions.DependencyInjection;  using Microsoft.Extensions.Hosting;    namespace WorkerServiceDemo  {      public class Program      {          public static void Main(string[] args)          {              CreateHostBuilder(args).Build().Run();          }            public static IHostBuilder CreateHostBuilder(string[] args) =>              Host.CreateDefaultBuilder(args)                  .ConfigureServices((hostContext, services) =>                  {                      services.AddHostedService<Worker>();                  });      }  }

Worker:

BackgroundService是实现了IHostedService的基类.调用 ExecuteAsync(CancellationToken) 来运行后台服务。实现返回一个Task,其表示后台服务整个生存期.在 ExeuteAsync(例如通过调用await)之前,不会启动任何其他服务.避免在ExecuteAsync中执行长时间的阻塞初始化. StopAsync(CancellationToekn) 中的主机块等待完成ExecuteAsync

调用 IHostedService.StopAsync 时,将触发取消令牌。 当激发取消令牌以便正常关闭服务时,ExecuteAsync 的实现应立即完成。 否则,服务将在关闭超时后不正常关闭。

using System;  using System.Collections.Generic;  using System.Linq;  using System.Threading;  using System.Threading.Tasks;  using Microsoft.Extensions.Hosting;  using Microsoft.Extensions.Logging;    namespace WorkerServiceDemo  {      public class Worker : BackgroundService      {          private readonly ILogger<Worker> _logger;            public Worker(ILogger<Worker> logger)          {              _logger = logger;          }            public override async Task StartAsync(CancellationToken cancellationToken)          {              await base.StartAsync(cancellationToken);          }            public override async Task StopAsync(CancellationToken cancellationToken)          {              await base.StopAsync(cancellationToken);          }            protected override async Task ExecuteAsync(CancellationToken stoppingToken)          {              while (!stoppingToken.IsCancellationRequested)              {                  _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                  await Task.Delay(1000, stoppingToken);              }          }            public override void Dispose()          {          }      }  }

已使用AddHostedService扩展方法在 IHostBuilder.ConfigureServices(Program.cs)中注册该服务。

 services.AddHostedService<Worker>();

WorkerServices部署到Windows服务

安装 WorkerServices模板

在IHostBuilder使用UseWindowsService扩展方法

using Microsoft.Extensions.DependencyInjection;  using Microsoft.Extensions.Hosting;      namespace WorkerServiceDemo  {      public class Program      {          public static void Main(string[] args)          {              CreateHostBuilder(args).Build().Run();          }            public static IHostBuilder CreateHostBuilder(string[] args)          {              return Host.CreateDefaultBuilder(args)                    .ConfigureServices((hostContext, services) =>                  {                      services.AddHostedService<Worker>();                  }).UseWindowsService(); ;            }      }  }

现在我们可以部署我们的windows服务了。

发布方式

  • 使用sc.exe工具
  • 直接部署exe文件

发布Windows服务

dotnet restore  dotnet publish

sc.exe部署

sc.exe create DemoWorker binpath= publishxxxx.exe  sc.exe start WorkerServicesName

部署exe文件

WorkerServicesName.exe install  WorkerServicesName.exe start

使用sc.exe停止和删除

sc.exe stop WorkerServicesName  sc.exe delete WorkerServicesName 

非sc.exe停止和删除

WorkerServicesName stop  WorkerServicesName uninstall

在Linux设置守护程序

添加Microsoft.Extensions.Hosting.Systemd NuGet软件包

将UseSystemd()添加上。

        public static IHostBuilder CreateHostBuilder(string[] args)          {                return Host.CreateDefaultBuilder(args)                  .ConfigureServices((hostContext, services) =>                  {                      services.AddHostedService<Worker>();                  }).UseSystemd();            }

在Linux上设置为守护程序。

Reference

https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-3.1&tabs=visual-studio

https://github.com/hueifeng/BlogSample/tree/master/src/WorkerServiceDemo