創建
首先你要確保你已經安裝了.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:\Windows\System32\sc.exe。這個網上教程一大堆,可以自行了解,這里不多介紹。
相關命令:
下面的 ServiceName 是自定義的,可以自行修改
## 創建服務 sc create ServiceName BinPath=E:\Work\Code\WindowsServiceDemo\WorkerService\bin\Debug\netcoreapp3.0\WorkerService.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:\Work\Code\WindowsServiceDemo\WorkerService\bin\Debug\netcoreapp3.0\WorkerService.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