打造跨平台.NET Core后台服务

续之前讲的在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

然后可以发现,程序可以正常运行。

img

补充

作为服务,应该要提供一些状态用于外部监测,在Worker.cs中,Worker类可以重写StartAsyncStopAsync方法,提供服务启动和停止的信息,但是windows提供的服务失败后动作等功能都找不到配置的地方,可能这就是局限吧。

总结

一次编写,处处运行,对于后台服务也是如此,很简洁。但是暂时手上没有mac电脑,也不知道mac上面有没有对应的解决方案。可能TopShelf的mono模式可以支持吧。

比较TopShelf模式

总体讲,相较于TopShelf的方式,Service Worker方式有利有弊。

优点:

  1. 在相同的框架(.NET CORE 3.0+)下支持跨平台,支持linux服务的systemctl管理,topshelf在linux下需要mono。
  2. 配置方式和ASP.NET CORE相似度极高,基本上可以无缝切换。

缺点:

  1. 不支持TopSelf的自带命令install/start/uninstall等命令,依然需要sc进行部署,比较麻烦。
  2. 不支持windows的很多服务管理特性(比如Pause,依赖管理)。
  3. 只支持.NET CORE 3.0以后的框架,不支持.NET FRAMEWORK和早期版本的.NET CORE。

参考资料

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


在上文中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发、订阅和处理的流程。这种实现太简单了,百十行代码就展示了一个基本工作原理。然而,要将这样的解决方案运用到实际生产环境,还有很长的路要走。今天,我们就研究一下在事件处理器中,对象生命周期的管理问题。事实上,不仅仅是在事件处理器
上文已经介绍了Identity Service的实现过程。今天我们继续,实现一个简单的Weather API和一个基于Ocelot的API网关。 回顾 《Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(一)》 Weather API Weather
最近我为我自己的应用开发框架Apworks设计了一套案例应用程序,并以Apache 2.0开源,开源地址是:https://github.com/daxnet/apworks-examples,目的是为了让大家更为方便地学习和使用.NET Core、最新的前端开发框架Angular,以及Apwork
HAL(Hypertext Application Language,超文本应用语言)是一种RESTful API的数据格式风格,为RESTful API的设计提供了接口规范,同时也降低了客户端与服务端接口的耦合度。很多当今流行的RESTful API开发框架,包括Spring REST,也都默认支
在前面两篇文章中,我详细介绍了基本事件系统的实现,包括事件派发和订阅、通过事件处理器执行上下文来解决对象生命周期问题,以及一个基于RabbitMQ的事件总线的实现。接下来对于事件驱动型架构的讨论,就需要结合一个实际的架构案例来进行分析。在领域驱动设计的讨论范畴,CQRS架构本身就是事件驱动的,因此,
HAL,全称为Hypertext Application Language,它是一种简单的数据格式,它能以一种简单、统一的形式,在API中引入超链接特性,使得API的可发现性(discoverable)更强,并具有自描述的特点。使用了HAL的API会更容易地被第三方开源库所调用,并且使用起来也很方便
何时使用领域驱动设计?其实当你的应用程序架构设计是面向业务的时候,你已经开始使用领域驱动设计了。领域驱动设计既不是架构风格(Architecture Style),也不是架构模式(Architecture Pattern),它也不是一种软件开发方法论,所以,是否应该使用领域驱动设计,以及什么时候使用
《在ASP.NET Core中使用Apworks快速开发数据服务》一文中,我介绍了如何使用Apworks框架的数据服务来快速构建用于查询和管理数据模型的RESTful API,通过该文的介绍,你会看到,使用Apworks框架开发数据服务是何等简单快捷,提供的功能也非常多,比如对Hypermedia的
在上一讲中,我们已经完成了一个完整的案例,在这个案例中,我们可以通过Angular单页面应用(SPA)进行登录,然后通过后端的Ocelot API网关整合IdentityServer4完成身份认证。在本讲中,我们会讨论在当前这种架构的应用程序中,如何完成用户授权。 回顾 《Angular SPA基于
Keycloak是一个功能强大的开源身份和访问管理系统,提供了一整套解决方案,包括用户认证、单点登录(SSO)、身份联合、用户注册、用户管理、角色映射、多因素认证和访问控制等。它广泛应用于企业和云服务,可以简化和统一不同应用程序和服务的安全管理,支持自托管或云部署,适用于需要安全、灵活且易于扩展的用
3月7日,微软发布了Visual Studio 2017 RTM,与之一起发布的还有.NET Core Runtime 1.1.0以及.NET Core SDK 1.0.0,尽管这些并不是最新版,但也已经从preview版本升级到了正式版。所以,在安装Visual Studio 2017时如果启用了
在上文中,我介绍了如何在Ocelot中使用自定义的中间件来修改下游服务的response body。今天,我们再扩展一下设计,让我们自己设计的中间件变得更为通用,使其能够应用在不同的Route上。比如,我们可以设计一个通用的替换response body的中间件,然后将其应用在多个Route上。 O
不少关注我博客的朋友都知道我在2009年左右开发过一个名为Apworks的企业级应用程序开发框架,旨在为分布式企业系统软件开发提供面向领域驱动(DDD)的框架级别的解决方案,并对多种系统架构风格提供支持。这个框架的开发和维护我坚持了很久,一直到2015年,我都一直在不停地重构这个项目。目前这个项目在
好吧,这个题目我也想了很久,不知道如何用最简单的几个字来概括这篇文章,原本打算取名《Angular单页面应用基于Ocelot API网关与IdentityServer4ʺSP.NET Identity实现身份认证与授权》,然而如你所见,这样的名字实在是太长了。所以,我不得不缩写“单页面应用”几个字
在前面两篇文章中,我介绍了基于IdentityServer4的一个Identity Service的实现,并且实现了一个Weather API和基于Ocelot的API网关,然后实现了通过Ocelot API网关整合Identity Service做身份认证的API请求。今天,我们进入前端开发,设计
Ocelot是ASP.NET Core下的API网关的一种实现,在微服务架构领域发挥了非常重要的作用。本文不会从整个微服务架构的角度来介绍Ocelot,而是介绍一下最近在学习过程中遇到的一个问题,以及如何使用中间件(Middleware)来解决这样的问题。 问题描述 在上文中,我介绍了一种在Angu
在大数据处理和人工智能时代,数据工厂(Data Factory)无疑是一个非常重要的大数据处理平台。市面上也有成熟的相关产品,比如Azure Data Factory,不仅功能强大,而且依托微软的云计算平台Azure,为大数据处理提供了强大的计算能力,让大数据处理变得更为稳定高效。由于工作中我的项目
在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容。下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了。其中绿色的部分就是上文中新实现的部分,包括一个简单的Event Store,一个事件处理器执行上下文的接
在之前《在ASP.NET Core中使用Apworks快速开发数据服务》一文的评论部分,.NET大神张善友为我提了个建议,可以使用Compile As a Service的Roslyn为语法解析提供支持。在此非常感激友哥给我的建议,也让我了解了一些Roslyn的知识。使用Roslyn的一个很大的好处
很长一段时间以来,我都在思考如何在ASP.NET Core的框架下,实现一套完整的事件驱动型架构。这个问题看上去有点大,其实主要目标是为了实现一个基于ASP.NET Core的微服务,它能够非常简单地订阅来自于某个渠道的事件消息,并对接收到的消息进行处理,于此同时,它还能够向该渠道发送事件消息,以便