博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用Topshelf把.NET Core Generic Host管理的应用程序部署为Windows服务
阅读量:5322 次
发布时间:2019-06-14

本文共 4287 字,大约阅读时间需要 14 分钟。

背景

2019第一篇文章。

此文源于前公司在迁移项目到.NET Core的过程中,希望使用Generic Host来管理定时任务程序时,没法部署到Windows服务的问题,而且官方也没给出解决方案,只能关注一下 等他们方解决了。

官方文档只提供了一个的方案,可以使用Microsoft.AspNetCore.Hosting.WindowsServices类库来把Web应用部署为Windows服务。但是ASP.NET Core虽然是控制台程序,但是它本身是使用了含有HTTP管道的Web Host来负责应用程序的生命周期管理,用它来作为定时任务的话,会有很多不必要的工作负载,例如占用端口、增加了很多依赖等等。

官方意识到这个问题之后,在.NET Core 2.1版本新增了Generic Host通用主机,剥离了原来WebHost的Http管道相关的API,源码中可以发现Web Host已经基于Generic Host实现。它才是作为纯粹定时任务程序的最佳拍档。

但是由于Generic Host本身非常简单,用它运行的程序设置在注册为Windows服务启动之后会自动停止。研究很久之后才知道,想在Windows上启动服务,还是不能像Linux上那么简单——

于是尝试结合Topshelf来创建Windows服务,最终成功了。

实现方法

  1. 先实现IHostLifetime接口来接管应用程序的生命周期,其实就是用空的实现来替换掉默认的ConsoleLifetime,这样就可以在之后由Topshelf框架内部去管理生命周期。
internal class TopshelfLifetime : IHostLifetime    {        public TopshelfLifetime(IApplicationLifetime applicationLifetime, IServiceProvider services)        {            ApplicationLifetime = applicationLifetime ?? throw new ArgumentNullException(nameof(applicationLifetime));        }        private IApplicationLifetime ApplicationLifetime { get; }        public Task WaitForStartAsync(CancellationToken cancellationToken)        {            return Task.CompletedTask;        }        public Task StopAsync(CancellationToken cancellationToken)        {            return Task.CompletedTask;        }    }
  1. 然后实现IHostedService接口,把后台任务逻辑写到StartAsync方法中,参见官方文档,本文示例使用定时写入文本到一个文件来测试定时任务是否成功运行。
internal class FileWriterService : IHostedService, IDisposable    {        private static string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"test.txt");        private Timer _timer;        public Task StartAsync(CancellationToken cancellationToken)        {            if (cancellationToken.IsCancellationRequested) return Task.FromCanceled(cancellationToken);            _timer = new Timer(                (e) => WriteTimeToFile(),                null,                TimeSpan.Zero,                TimeSpan.FromSeconds(10));            return Task.CompletedTask;        }        public void WriteTimeToFile()        {            if (!File.Exists(path))            {                using (var sw = File.CreateText(path))                {                    sw.WriteLine(DateTime.Now);                }            }            else            {                using (var sw = File.AppendText(path))                {                    sw.WriteLine(DateTime.Now);                }            }        }        public Task StopAsync(CancellationToken cancellationToken)        {            _timer?.Change(Timeout.Infinite, 0);            return Task.CompletedTask;        }        public void Dispose()        {            _timer?.Dispose();        }    }
  1. 构建Generic Host,在ConfigureServices方法中注册TopshelfLifetime,并且注册一个托管服务FileWriterService,就能完成Generic Host的简单构建,当然完整的项目应该还包含配置、日志等等。最后,使用Topshelf来接管Generic Host,创建Windows服务。
internal class Program    {        private static void Main(string[] args)        {            var builder = new HostBuilder()                .ConfigureServices((hostContext, services) =>                {                    services.AddSingleton
(); services.AddHostedService
(); }); HostFactory.Run(x => { x.SetServiceName("GenericHostWindowsServiceWithTopshelf"); x.SetDisplayName("Topshelf创建的Generic Host服务"); x.SetDescription("运行Topshelf创建的Generic Host服务"); x.Service
(s => { s.ConstructUsing(() => builder.Build()); s.WhenStarted(service => { service.Start(); }); s.WhenStopped(service => { service.StopAsync(); }); }); }); } }
  1. 最后发布应用程序,并安装到Windows服务。

以管理员权限开启终端,执行命令:

dotnet publish -c release -r win-x64    cd path-to-project/bin/release/netcoreapp2.1/win-x64/publish  ./project-name install  net start GenericHostWindowsServiceWithTopshelf

generic-host-install.png

这样这个Windows服务就启动了!查看输出文件,可以看到定时写入成功,服务也一直没关闭~

generic-host-result.png

示例代码

https://github.com/ElderJames/GenericHostWindowsServiceWithTopshelf

参考链接

官方文档

官方文档

转载于:https://www.cnblogs.com/ElderJames/p/Using-Topshelf-To-Deploy-Net-Core-Generic-Host-App-To-Windows-Services.html

你可能感兴趣的文章
类 的重载(Overloads)与隐藏(Shadows)
查看>>
快速部署简单私有云CloudStack(上)
查看>>
状态模式
查看>>
django简介
查看>>
搜索动态库时查找目录的先后顺序
查看>>
vue工程按业务路由打包,页面只加载对应资源
查看>>
第三十三天-rsync高级同步工具深度实战
查看>>
Azure SQL 数据库仓库Data Warehouse (1) 入门
查看>>
常用DOM结构方法总结
查看>>
数据挖掘算法之关联规则挖掘(二)FPGrowth算法
查看>>
final域的内存语义
查看>>
perl处理menu菜单项,把代码转成fbp文件格式
查看>>
学习进度条博客
查看>>
unix网络编程 str_cli epoll 非阻塞版本
查看>>
JS规则 给变量取个名字(变量命名) 必须以字母、下划线或美元符号开头;区分大小写;不允许使用JS关键字或保留字...
查看>>
如何利用Python网络爬虫爬取微信朋友圈动态--附代码(下)
查看>>
pcie dma的玩法
查看>>
BZOJ1043 [HAOI2008]下落的圆盘
查看>>
SqlDbx连接oracle(无需安装Oracle客户端)
查看>>
关于Membership和身份认证的记录
查看>>