asp.net core很大的方便了跨平臺的開發者,linux的開發者可以使用apache和nginx來做反向代理,windows上可以用IIS進行反向代理。 反向代理可以提供很多特性,固然很好。但是還有複雜性,我們也可以使用windows service來直接啟動kestrel。 asp.net ...
asp.net core很大的方便了跨平臺的開發者,linux的開發者可以使用apache和nginx來做反向代理,windows上可以用IIS進行反向代理。
反向代理可以提供很多特性,固然很好。但是還有複雜性,我們也可以使用windows service來直接啟動kestrel。
asp.net core官方網站提供了一種基於windows服務部署的方法:在 Windows 服務中托管 ASP.NET Core
這種方式需要修改代碼,然後部署的時候,使用命令行創建、安裝服務,然後再啟動。
感覺還是不夠爽快,我們可以使用topshelf改造一下。
TopShelf
topshelf可以很便捷地將一個windows console程式改造成windows service,只需要稍微修改一下代碼結構,然後通過nuget包就可以簡單操作了。安裝與部署也是極其方便,而且,topshelf在調試的時候,直接是作為console程式,極其便於調試。
TopShelf項目地址:http://topshelf-project.com/
步驟
首先引用nuget包:
Install-Package TopShelf
然後改造一下program.cs
public class Program
{
public static void Main(string[] args)
{
var rc = HostFactory.Run(x => //1
{
x.Service<MainService>(s => //2
{
s.ConstructUsing(name => new MainService(args)); //3
s.WhenStarted(tc => tc.Start()); //4
s.WhenStopped(tc => tc.Stop()); //5
});
x.RunAsLocalSystem(); //6
x.SetDescription("JwtAPIService"); //7
x.SetDisplayName("JwtAPIService"); //8
x.SetServiceName("JwtAPIService"); //9
}); //10
var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode()); //11
Environment.ExitCode = exitCode;
//CreateWebHostBuilder(args).Build().RunAsService();
}
}
這裡指定服務程式的內容在MainService
這個類裡面,並通過代碼指定了服務的名稱和描述等行為。以前的啟動CreateWebHostBuilder方法轉移到了這個類中:
public class MainService
{
private string[] args;
public MainService(string[] vs)
{
args = vs;
}
public void Start()
{
var isService = !(Debugger.IsAttached || args.Contains("--console"));
var builder = CreateWebHostBuilder(args.Where(arg => arg != "--console").ToArray());
if (isService)
{
var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
var pathToContentRoot = Path.GetDirectoryName(pathToExe);
builder.UseContentRoot(pathToContentRoot);
}
var host = builder.Build();
host.Run();
}
public void Stop()
{
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var config = new ConfigurationBuilder()
// .SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config.json", optional: true, reloadOnChange: true)
.Build();
return WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseConfiguration(config)
.UseStartup<Startup>();
}
}
Start方法指定服務啟動時,服務的執行不需要依賴於Microsoft.AspNetCore.Hosting.WindowsServices這個nuget包。
另外Contentroot需要註意,使用windows服務進行提供服務,GetCurrentDirectory的根目錄是system32,而不是asp.net core的dll的目錄。使用appsettings.json時,可能會引起問題,最好使用自定義的程式配置(例如這裡通過config.json進行設置)。
運行
- 確定是否存在 Windows 運行時標識符 (RID),或將其添加到包含目標框架的
中:
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
</PropertyGroup>
- 發佈,最終可以得到可執行程式。直接雙擊運行,程式就可以以console的形式啟動,方便調試。
- 命令行運行xxxx.exe install就而可以安裝服務,然後服務就可以自動啟動。
- 命令行運行xxxx.exe uninstall就可以卸載服務。整個過程不需要新建用戶與策略。
後記
吐槽:直接使用TopShelf,調試windows服務的過程變得不那麼痛苦了,想起附加調試器的過程,簡直了。
P.S. 需要最新版本的topshelf才可以支持asp.net core的服務部署。