运行 docker 中的 c# worker 服务有意义吗?

Does it make sense to run a c# worker service in docker?

我正在 docker 中开发一个多容器应用程序。其中一项服务是 C# 中的 long-运行 控制台应用程序,它基本上对数据库进行一些轮询并将数据发送到 e 服务器。我只是通过添加以下语句来保留服务 运行:

while(true);

现在我正在考虑将此服务更改为 .NET Core worker 服务(甚至 windows 服务,因为我只在 windows 主机上使用 windows 容器) .我已经阅读了一些关于工作人员服务的优点的文章,但是当涉及到容器化应用程序时,它们似乎都已经过时了,因为我的容器无论如何都是 运行 作为一种“后台服务”(而且我只使用一种服务每 container/image)。所以我的问题是:

运行 docker 中的核心辅助服务与 docker 中的 运行 控制台应用程序相比,有什么好处或缺点吗?

更新:对于“工作者服务”,我指的是 .NET Core 中可用的新工作者服务模板 3.x:https://www.stevejgordon.co.uk/what-are-dotnet-worker-services

简而言之,您的快乐路径代码的功能可能“大致相同”。

然而:

使用“通用主机”的好处是您可以享受 Microsoft 为您创建的可重用组件的好处......而不是自己动手。

这意味着(恕我直言)更好的代码,因为您不需要亲自处理大量 运行ning 过程中的常见问题。

基本上,与滚动您自己的实现相比,您会“免费”获得大量管道代码。

Pre 3.0/3.1 许多此功能已与 asp.net 名称空间结合。 3.0/3.1 更新有很多“将其放入 asp.net 和 .net(非 asp.net)的公共位置”以供使用。 Aka,与 asp.net.

分手

设置:(专用方法“AddHostedService”)

services.AddHostedService<MyWorkerThatImplementsIHostedService>();

因此,当未来的开发人员查看上面的代码时,他们会确切地知道发生了什么。 (与找出自定义滚动实现相比)

或者在更大的代码示例中:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices(services =>
            {
                services.AddHostedService<MyWorkerThatImplementsIHostedService>();
            });
}

上面的代码~~看起来~~ asp.net'ish,但实际上是.net(非asp.net)代码。 也就是说,您的一致性得到了提高。

关机:

您获得了所有内置的“关闭”选项。这些都是“正常”关闭选项……不幸的是,“快乐之路”开发人员通常不会考虑这些选项。如果有任何理由跳进这个迷你图书馆......有某种优雅的出口就是这样。硬退出可能会使您的处理处于未知的难以排除故障的状态。

CNLT-C

Programmatically (see https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostapplicationlifetime.stopapplication?view=dotnet-plat-ext-3.1 )

Kubernetes Shutdown

微软甚至想出了“我能不能把最终关机延迟一些”

参见:

这是一个不错的 link,它显示了一些选项(计时器、队列和监视器)

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio

您还可以将代码部署为:

容器

Windows 服务

** Linux 守护进程(参见 https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.systemd.systemdhelpers.issystemdservice?view=dotnet-plat-ext-3.1 )(这对于传统的 dotnet 框架开发人员来说通常是一个新概念)

Azure 应用服务

哦,是的,Microsoft 甚至为您设计了“HealthChecks”。

https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-5.0#separate-readiness-and-liveness-probes-1

瓶口线,用这个代替定制的卷材。考虑周全。

::::::::::::::::::::::以前的评论:::::::::::::::::::::::: ::::::::::(下)

.......

Long-运行C# 中的 ning 控制台应用程序

短版:

对于现代代码部署策略,这不仅仅是技术决策,还是财务决策。

更长的版本:

我最近讨论过这个问题,因为一些代码库已指定用于“转换为 dotnet 核心”和“我们如何转换旧的 windows 服务?”。

这是我的想法:

哲学上。

您必须考虑“我在哪里部署以及部署成本是多少?”,而不仅仅是技术问题。你提到 docker。但是你如何部署它?库伯内斯? (天蓝色的AKS,其他?)这是一条重要的信息。

恕我直言:使用“云”甚至本地 Kubernetes ....你不需要“Windows 服务”的心态,那只会 运行 和 运行 运行、运行不断增加成本。除非你拥有这个。

您想启动一个进程,让它运行,并尽快关闭它。

现在,如果您需要每小时 运行,那很好。

现在,如果您需要“即时”或“尽快处理”(例如查看队列中的消息),那么也许您付出了代价并拥有了 运行 全部的东西时间,因为处理这些消息比您为 运行ning 服务支付的价格更重要。

从技术上讲,我喜欢

的想法

https://www.stevejgordon.co.uk/what-are-dotnet-worker-services

WHAT ARE WORKER SERVICES? Applications which do not require user interaction. Use a host to maintain the lifetime of the console application until the host is signalled to shut down. Turning a console application into a long-running service. Include features common to ASP.NET Core such and dependency injection, logging and configuration. Perform periodic and long-running workloads.

但在财务上,我必须用 运行在 Azure 上(甚至在内部部署)的成本来抵消这一点。

处理 Message Queue 消息意味着 --> “是的,必须一直 运行”。所以我一直都在为拥有它付出代价运行。

如果我知道我的客户一次在半夜发布他们的导入文件,那么我不想支付总是 运行ning 的价格。我想要一个早上触发一次的控制台应用程序。进来,出去。尽快处理并离开。 Kubernetes 有调度机制。

对于 Azure,这不仅仅是技术决策,还是财务决策。

未提及:如果您的代码计划每小时 运行,但随后开始花费超过一小时 运行,您会遇到不同的问题。 Quartz.Net 是处理这些重叠问题的一种方法。

请记住,我必须对这个关于成本的争论非常坚定。大多数开发人员只想将 windows-services 转换为 dotnet-core 并完成它。但这不是长期的想法,因为越来越多的代码转移到云中,云操作的成本开始发挥作用。

PS

此外,请确保将所有代码向下移动到业务层........并让这些方法中的任何一种

  • Console.App(普通一个)

  • .NET Core 工作者服务

  • Quartz.Net 安排作业[=​​20=]

让上面的项目成为“调用您的业务逻辑层的薄顶层”,然后您就不会把自己逼到墙角了。你做的顶层越薄越好。基本上,我的控制台应用程序是

void Main(string args)
{
  //wire up IoC
  //pull out the business logic layer object from the Ioc
  //call a single method on the business logic layer
}

和一些 appsettings.json 文件被 Program.cs 坐下。没有或很少。尽快将一切下推到业务逻辑层。

如果您总是要在容器中 运行,那么请使用控制台应用程序。我认为 运行ning 作为一种服务并没有内在的好处,因为在 Kubernetes 等适当的编排下,容器应该被认为是短暂的。此外,运行将您的 .NET Core 3.1.x 应用程序作为 Linux 或 Windows 容器时,如果您保持简单,即控制台。

此外,我会在您的控制台中使用以下行,以确保它与为容器分配的 CPU 兼容:

while(true)
{
    Thread.Sleep(1 * 1000);
}