创建
首先你要确保你已经安装了.NET Core 3.0或以上版本。
老版本的Windows服务请看 这篇文章
- 使用命令行创建: dotnet new worker
- 使用Visual Studio创建
中文版:
英文版:
创建的新项目包含两个文件。其中 Program.cs 文件是应用的启动程序。另外一个文件是 Worker.cs 文件,你可以在这个文件编写你的业务代码。
这看起来应该是相当的容易,但是为这个程序添加额外的并行后台服务,你还需要添加一个类,并让它继承 BackgroundService 类:
public class MyNewBackgroundWorker : BackgroundService { protected override Task ExecuteAsync(CancellationToken stoppingToken) { //Do something. } }
然后在 Program.cs 中,我们要做的只是把当前的Worker注册到服务集合(Service Collection)中即可。
.ConfigureServices((hostContext, services) => { services.AddHostedService<Worker>(); services.AddHostedService<MyNewBackgroundWorker>(); });
实际上作为“后台服务”任务的运行程序, AddHostedService 方法已经在框架中存在了很长时间了。在之前我们已经完成的一篇关于ASP.NET Core托管服务的文章, 但是在当时场景中,我们托管是是整个应用,而非一个在你应用程序幕后运行的东西。
优化系统的 Worker.cs ,代码执行顺序是冲上往下依次执行的(程序开始-停止)
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace WorkerService { public class Worker : BackgroundService { private readonly ILogger<Worker> _logger; public Worker(ILogger<Worker> logger) { _logger = logger; } public override Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation($"Worker started at: {DateTime.Now}"); return base.StartAsync(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 Task StopAsync(CancellationToken cancellationToken) { _logger.LogError($"Worker stopped at: {DateTime.Now}"); return base.StopAsync(cancellationToken); } public override void Dispose() { _logger.LogInformation($"Worker disposed at: {DateTime.Now}"); base.Dispose(); } } }
部署Windows服务
需要引用 Microsoft.Extensions.Hosting.WindowsServices Neget 包
Install-Package Microsoft.Extensions.Hosting.WindowsServices
修改 Program.cs 文件,添加 UseWindowsService() 方法调用
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { services.AddHostedService<Worker>(); }) .UseWindowsService();
这样代码部分就完成了。
然后使用 cmd 命令把我们发布后的程序代码部署成Windows服务,需要使用管理员权限运行CMD
借助 sc.exe 工具。sc.exe是帮助开发部署 WindowsNT 服务的工具,路径: C:WindowsSystem32sc.exe。这个网上教程一大堆,可以自行了解,这里不多介绍。
相关命令:
下面的 ServiceName 是自定义的,可以自行修改
## 创建服务 sc create ServiceName BinPath=E:WorkCodeWindowsServiceDemoWorkerServiceinDebug etcoreapp3.0WorkerService.exe ## 启动服务 sc start ServiceName ## 停止服务 sc stop ServiceName ## 删除服务 sc delete ServiceName ## 添加服务描述 sc description ServiceName "描述" ## 改变服务的启动方式 手动/自动/禁用 sc config ServiceName start= demand/auto/disabled
install.bat
set serviceName=ServiceName set serviceFilePath=E:WorkCodeWindowsServiceDemoWorkerServiceinDebug etcoreapp3.0WorkerService.exe set serviceDescription=服务描述 sc create %serviceName% BinPath=%serviceFilePath% sc config %serviceName% start=auto sc description %serviceName% %serviceDescription% sc start %serviceName% pause
unstall.bat
set serviceName=ServiceName sc stop %serviceName% sc delete %serviceName% pause
最后使用管理员权限运行 install.bat
查看下服务面板
以上是参考 这边文章 编写的。
部署Linux服务
环境:一台全新的Centos 7.7.1908 系统
安装 .net core相关环境
参考:https://docs.microsoft.com/zh-cn/dotnet/core/install/linux-package-manager-centos7
注册 Microsoft 密钥和源:
sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
安装 .NET Core SDK:
sudo yum install dotnet-sdk-3.0 -y
安装完成之后可以输入 dotnet --version 查看是否可以返回对应版本
修改代码
程序代码需要引用 Microsoft.Extensions.Hosting.Systemd Neget包
Install-Package Microsoft.Extensions.Hosting.Systemd
修改 Program.cs 文件,添加 UseSystemd() 方法调用,可以和 UseWindowsService() 共存
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { services.AddHostedService<Worker>(); }) .UseWindowsService() .UseSystemd();
然后把发布文件移至linux系统
部署服务
linux的服务是通过systemd守护进程部署的。现在在系统中我们有了一个发布后的应用程序,我们需要为systemd创建配置文件部署服务。步骤如下:
创建一个.service文件(我们要部署服务,因此需要.service文件),填入以下内容。可以在Linux中直接创建或者通过windows创建然后拷贝至linux。
[Unit] Description= my test app
[Service] Type=notify ExecStart=/usr/bin/dotnet /home/demo/WorkerService.dll [Install] WantedBy=multi-user.target
Description:描述,看个人需要是否添加。不需要可以去掉。只留下 [Service] 和 [Install]
Type=notify:当前服务启动完毕,会通知Systemd
,再继续往下执行
ExecStart:启动当前服务的命令,程序如何启动,第一个路径是固定路径。第二个路径是应用程序的dll路径(可以自定义)
WantedBy:表示该服务所在的 Target服务组, multi-user.target,表示多用户命令行状态。
把 .service文件移动至 /etc/systemd/system/ 固定目录下,假设自定义文件名称为:testapp.service(如果使用其他名称,请更改testapp)
使用systemctl命令重新加载新的配置文件
sudo systemctl daemon-reload
查看相关服务状态
sudo systemctl status testapp
您应该看到类似以下的内容:
这表明您已注册的新服务已禁用,我们可以通过运行以下命令来启动我们的服务:
sudo systemctl start testapp.service
重新运行 sudo systemctl status testapp 查看服务状态显示已激活正在运行中
设置服务开机自启
sudo systemctl enable testapp.service
到此我们的服务已经完整的部署到了linux系统中
现在我们有一个运行了systemd的应用程序,我们可以看看日志记录集成。使用systemd的好处之一是可以使用journalctl访问的集中式日志记录系统。
首先,我们可以使用journalctl(访问日志的命令)查看服务日志:
sudo journalctl -u testapp
可以看到我们的程序正在运行,可以使用 ↑↓ ← →查看日志内容。或者使用grep搜索。q 键退出
卸载自定义服务
servicename=testapp.service systemctl stop $servicename systemctl disable $servicename rm -rf /etc/systemd/system/$servicename rm -rf /etc/systemd/system/$servicename symlinks that might be related systemctl daemon-reload systemctl reset-failed
相关链接
部署Windows服务相关链接:
https://www.cnblogs.com/lwqlun/p/12038062.html
https://devblogs.microsoft.com/aspnet/net-core-workers-as-windows-services/
https://www.cnblogs.com/Rwing/p/net-core-workers-as-windows-services.html
自定义安装服务相关配置相关链接:
http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html
https://www.cnblogs.com/jhxxb/p/10654554.html
systemd命令相关链接:
https://www.cnblogs.com/tsdxdx/p/7288490.html
http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html
https://www.cnblogs.com/zyh121344305/p/8677015.html
https://www.cnblogs.com/jhxxb/p/10654554.html
部署Linux服务相关链接:
https://devblogs.microsoft.com/dotnet/net-core-and-systemd/
https://stackoverflow.com/questions/51589504/asp-net-core-2-0-unable-to-start-service-on-debian
源码地址:https://github.com/RainFate/WindowsServiceDemo/tree/Init/WorkerService