續之前講的在TopShelf上部署ASP.NET Core程式,作為后臺服務運行,自從.NET Core 3.0出現以后,出現了自帶的Generic Host,使得自托管服務變為可能,這種方式和TopShelf方式一樣,可以直接F5進行服務的除錯,也為跨平臺后臺服務撰寫提供了一種新的方案,
創建服務
以VS2019為例,確保安裝了.NET CORE 3.0以上的SDK,新建專案,在專案模板里面可以找到Worker Service模板,創建后,vs已經幫我們創建了Program.cs和Worker.cs兩個檔案,
在Program.cs中,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace WorkerServiceTest
{
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>();
});
}
}
}
可以發現,配置的方式和ASP.NET CORE的方式基本一樣一樣的,使用了內置的DI容器,那我們同樣可以使用AddSingleton等方法進行其他邏輯的注入,也可以添加多個服務任務,
而Worker類已經寫了好一個范例,其中有一個ExecuteAsync方法,可以直接執行后臺任務,這個時候,直接F5就可以正常運行了,自帶了一個顯示當前時間的小程式,
跨平臺支持
雖然程式可以正常執行,但是還不能正常部署為服務,需要依據平臺添加對應的nuget包:
- windows服務,需要添加:
Install-Package Microsoft.Extensions.Hosting.WindowsServices
- Linux服務,需要添加:
Install-Package Microsoft.Extensions.Hosting.Systemd
如果想實作一套程式多處運行,那么直接同時安裝兩個package就可以了,接下來在CreateHostBuilder中,添加UseWindowsService()和UseSystemd(),
public static IHostBuilder CreateHostBuilder(string[] args)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
}).UseWindowsService();
}
else
{
return Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
}).UseSystemd();
}
}
這里使用到了.NET Core判斷平臺的一個函式:IsOSPlatform,可以判斷是否在Windows平臺運行,并進行分別呼叫,
部署
編譯完成之后,找到生成的exe檔案路徑,
Windows下部署
管理員下運行cmd/powershell,執行
sc.exe create WorkerServiceTest binPath=C:\Users\source\repos\WorkerServiceTest\WorkerServiceTest\bin\Debug\netcoreapp3.1\WorkerServiceTest.exe
提示CreateService 成功即安裝成功了,可以輸入下面的命令運行服務,
sc.exe start WorkerServiceTest
sc.exe負責管理服務,具體配置啟動方式和洗掉,可以查看命令的幫助,另外,友情提醒,如果是在powershell中,不要省略這個.exe,sc有別的用處...
Linux下部署
將整個程式檔案夾傳輸到Linux檔案夾下,我這邊使用的是CentOS 8,新建一個運行服務的用戶:
useradd -m dotnetuser -p dotnetpass
轉到/etc/systemd/system檔案夾,建立一個WorkerServiceTest.service的檔案,這個WorkerServiceTest是你的服務名稱,
輸入以下內容并保存(systemd組態檔):
[Unit]
Description=WorkerServiceTest
[Service]
ExecStart=dotnet /bin/dotnet/WorkerServiceTest.dll
WorkingDirectory=/bin/dotnet/
User=dotnetuser
Group=dotnetuser
Restart=on-failure
SyslogIdentifier=WorkerServiceTest
PrivateTmp=true
[Install]
WantedBy=multi-user.target
注意,你需要已經安裝有dotnet runtime 3.0以上版本才可以,
可以使用以下命令進行安裝
yum install dotnet-runtime-3.1
接下來是配置服務和啟動服務
#多載配置
systemctl daemon-reload
#設定服務自動啟動
systemctl enable WorkerServiceTest.service
#運行服務
systemctl start WorkerServiceTest.service
#查詢服務狀態
systemctl status WorkerServiceTest.service
然后可以發現,程式可以正常運行,

補充
作為服務,應該要提供一些狀態用于外部監測,在Worker.cs中,Worker類可以重寫StartAsync和StopAsync方法,提供服務啟動和停止的資訊,但是windows提供的服務失敗后動作等功能都找不到配置的地方,可能這就是局限吧,
總結
一次撰寫,處處運行,對于后臺服務也是如此,很簡潔,但是暫時手上沒有mac電腦,也不知道mac上面有沒有對應的解決方案,可能TopShelf的mono模式可以支持吧,
比較TopShelf模式
總體講,相較于TopShelf的方式,Service Worker方式有利有弊,
優點:
- 在相同的框架(.NET CORE 3.0+)下支持跨平臺,支持linux服務的systemctl管理,topshelf在linux下需要mono,
- 配置方式和ASP.NET CORE相似度極高,基本上可以無縫切換,
缺點:
- 不支持TopSelf的自帶命令install/start/uninstall等命令,依然需要sc進行部署,比較麻煩,
- 不支持windows的很多服務管理特性(比如Pause,依賴管理),
- 只支持.NET CORE 3.0以后的框架,不支持.NET FRAMEWORK和早期版本的.NET CORE,
參考資料
- https://devblogs.microsoft.com/aspnet/net-core-workers-as-windows-services/
- https://devblogs.microsoft.com/dotnet/net-core-and-systemd/
- https://docs.microsoft.com/en-us/dotnet/core/extensions/generic-host
- https://dejanstojanovic.net/aspnet/2018/june/setting-up-net-core-servicedaemon-on-linux-os/
- https://dotnetcoretutorials.com/2019/12/07/creating-windows-services-in-net-core-part-3-the-net-core-worker-way/
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/195309.html
標籤:.NET Core
上一篇:【Azure DevOps系列】Azure DevOps多階段構建
下一篇:C#-運算式目錄樹
