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 的服务部署.
来源: https://www.cnblogs.com/podolski/p/10054286.html