.NET Core Generic Host Windows服务部署使用Topshelf

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

官方文档只提供了一个《在 Windows 服务中托管 ASP.NET Core》的方案,可以使用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|1实现方法

  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方法中,参见官方文档《在 ASP.NET Core 中使用托管服务实现后台任务》,本文示例使用定时写入文本到一个文件来测试定时任务是否成功运行。
    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<IHostLifetime, TopshelfLifetime>();
                    services.AddHostedService<FileWriterService>();
                });

            HostFactory.Run(x =>
            {
                x.SetServiceName("GenericHostWindowsServiceWithTopshelf");
                x.SetDisplayName("Topshelf创建的Generic Host服务");
                x.SetDescription("运行Topshelf创建的Generic Host服务");

                x.Service<IHost>(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

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

1|2示例代码

https://github.com/ElderJames/GenericHostWindowsServiceWithTopshelf

1|3参考链接

官方文档《.NET 通用主机》

官方文档《在 ASP.NET Core 中使用托管服务实现后台任务》

__EOF__

作  者:ElderJames

原文地址:https://www.cnblogs.com/Leo_wl/p/10304358.html

时间: 2024-09-29 22:12:25

.NET Core Generic Host Windows服务部署使用Topshelf的相关文章

windows服务部署与卸载

同事问到windows service的东东,现在整理一下,用c#如何创建一个windows service,以及如何调试.部署.卸载. 一.创建windows service 1. 打开VS2008,新建一个Project, Project类型选择Visual C#-Windows,在Templates中选择Windows Service, 其他可以默认,点击OK. 2. 在Solution Explorer中会看到自动产生了三个文件:app.config, Program.cs,Servic

Windows 服务开发框架介绍 - Topshelf

关于 TopShelf Topshelfis a framework for hosting services written using the .NET framework. The creation of services is simplified, allowing developers to create a simple console application that can be installed as a service using Topshelf. The reason

dotnet-warp &amp;&amp; NSSM 部署 .net core 项目到 windows 服务

如果你想将 .net core 项目以服务的形式部署到 windows 系统,希望本篇文章能够让你少走弯路 dotnet-warp 安装使用 dotnet-warp 是一个全局的.NET Core 工具,允许将.NET Core 项目打包为单个可执行文件 项目地址:https://github.com/Hubert-Rybak/dotnet-warp 安装:dotnet tool install --global dotnet-warp 使用:在项目输出目录执行 dotnet-warp 即可将应

JavaService以Windows服务部署jar包

在生产环境,可执行jar包如果仅以 java -jar的方式运行,多个后台服务进程名称区分不清,且重启等无法自动控制: 所以使用java service,将jar包以windows服务的方式部署在服务器中. JavaService.exe -install aaaService "%JAVA_HOME%\jre\bin\server\jvm.dll" -Djava.class.path="G:\lrh\code\goodsMonitor\export\GoodsMonitor

windows服务部署

1.新建windows服务项目 2.编辑业务代码 我这里只写2句记录文本的测试代码 using System; using System.IO; using System.ServiceProcess; namespace WindowsService { public partial class Service : ServiceBase { public Service() { InitializeComponent(); } protected override void OnStart(

ASP.NET Core使用TopShelf部署Windows服务

asp.net core很大的方便了跨平台的开发者,linux的开发者可以使用apache和nginx来做反向代理,windows上可以用IIS进行反向代理. 反向代理可以提供很多特性,固然很好.但是还有复杂性,我们也可以使用windows service来直接启动kestrel. asp.net core官方网站提供了一种基于windows服务部署的方法:在 Windows 服务中托管 ASP.NET Core 这种方式需要修改代码,然后部署的时候,使用命令行创建.安装服务,然后再启动. 感觉

如何优雅的利用Windows服务来部署ASP.NET Core程序

上一篇文章中我给大家讲述了五种部署ASP.NET Core网站的方法,其中有一种方式是通过Windows服务来进行部署,这样既可以做到开启自启动,又不会因为iis的反向代理而损失部分性能.但是美中不足的是需要借助第三方软件nssm来进行,那么有没有更好并且优雅的方式来进行ASP.NET Core网站的Windows服务方式部署呢?答案是肯定的! 作者:依乐祝 原文链接:https://www.cnblogs.com/yilezhu/p/10380887.html 今天这篇文章我会利用番茄工作法来

使用.Net Core 2.2创建windows服务

使用.Net Core 2.2创建windows服务 我的环境 win 10 home Visual Studio 2019 v16.1.3 安装有.net core 2.2 创建项目 编辑项目文件 在 PropertyGroup 配置节 加入属性 <RuntimeIdentifier>win-x64</RuntimeIdentifier> 保存后,重新生成项目 在项目文件夹下,会有文件夹 bin\Debug\netcoreapp2.2\win-x64,里面包含了exe文件. 测试

在windows服务中托管asp.net.core

参考:https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-3.1&tabs=visual-studio 背景:项目各个模块部署在不同位置,因此采用了微服务架构.由于安装部署环境的差异,部分模块只能部署在xp系统下,其他部署环境考虑使用net.core,在windows服务中托管webapi,或者在webapi中寄宿windows服务,总而言之就是在一个程序中将wi