使用 .NET 6 构建跨平台 Worker Service 服务:跨越平台的 C# 服务开发——解决Windows服务跨平台问题

现代软件开发中,构建跨平台的应用程序变得愈加重要。C# 和 .NET 6 的出现使得在 Windows、Linux 和 macOS 上创建背景服务变得简单而高效。在本指南中,我们将通过创建一个使用 .NET 6 的 Worker Service 来展示如何实现跨平台后台服务。

项目概述

我们将创建一个简单的后台服务,该服务每隔一秒记录当前时间到日志中。此示例将使用 Visual Studio 2022 的 Worker Service 模板来实现,并演示如何在不同的平台上运行和部署。

1. 创建跨平台 Worker Service

1.1 安装 Visual Studio 2022

确保您已经安装了 Visual Studio 2022,并且在安装过程中选择了 ".NET 6.0" 工作负载。

1.2 创建 Worker Service 项目

  1. 启动 Visual Studio 2022。
  2. 点击 "创建新项目"。
  3. 在搜索框中输入 "Worker"。
  4. 选择 "Worker Service" 模板,点击 "下一步"。
  5. 输入项目名称(例如 MyCrossPlatformService),选择位置并点击 "创建"。

此时,Visual Studio 将生成一个基本的 Worker Service 项目结构。

2. 项目结构

创建的项目结构如下:

cs 复制代码
MyCrossPlatformService/
├── MyCrossPlatformService.csproj
├── Program.cs
└── Worker.cs

3. 实现 Worker Service服务

3.1 编辑 Worker.cs

打开 Worker.cs 文件,修改代码以实现每隔一秒记录当前时间的逻辑:

cs 复制代码
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken); // 每秒执行一次
        }
    }
}

4. 配置主程序

4.1 编辑 Program.cs

Program.cs 中配置和启动应用:

cs 复制代码
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

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>();
            });
}

5. 运行服务

5.1 在 Windows 上运行

在 Visual Studio 2022 中,可以直接使用调试工具运行服务:

  1. 点击菜单中的 "调试" > "开始调试"(或按 F5)。
  2. 控制台窗口将打开,并每秒记录当前时间。

5.2 在 Linux 上运行

要在 Linux 上运行此服务,您需要发布它并使用命令行运行。可以使用以下步骤:

  1. 在 Visual Studio 中右键单击项目,选择 "发布"。
  2. 选择目标(例如文件夹),设置输出路径,并选择发布配置(Release)。
  3. 点击 "发布"。

发布完成后,您可以将输出文件夹中的内容部署到 Linux 系统上,然后使用以下命令运行:

cs 复制代码
dotnet MyCrossPlatformService.dll

6. 部署为系统服务

在 Linux 上,可以将该应用注册为 systemd 服务以便于管理。

6.1 创建 systemd 服务文件

创建一个 systemd 服务文件,文件名为 /etc/systemd/system/mycrossplatformservice.service,内容如下:

XML 复制代码
[Unit]
Description=My Cross-Platform Service

[Service]
WorkingDirectory=/path/to/your/publish
ExecStart=/usr/bin/dotnet /path/to/your/publish/MyCrossPlatformService.dll
Restart=always
SyslogIdentifier=mycrossplatformservice

[Install]
WantedBy=multi-user.target

确保将 /path/to/your/publish 替换为您实际的发布路径。

6.2 启用和启动服务

执行以下命令启用并启动服务:

cs 复制代码
sudo systemctl enable mycrossplatformservice
sudo systemctl start mycrossplatformservice

6.3 检查服务状态

您可以使用以下命令检查服务的状态:

cs 复制代码
sudo systemctl status mycrossplatformservice

7. 日志记录

7.1 配置日志记录

在 Worker 中,我们使用了 ILogger<Worker> 来记录信息。在 Visual Studio 中,您可以通过 appsettings.json 文件配置日志记录设置。例如:

XML 复制代码
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

我们也可以使用log4net、NLog等第三方日志库来记录日志,尤其是log4net非常的强大,具体使用在此不进行具体介绍,因为网络上资源很多了。

8. 高级特性与扩展

在完成基本服务后,可以通过以下方式进一步增强服务的功能和可维护性:

8.1 使用依赖注入

您可以通过依赖注入来实现服务间的解耦。

添加自定义服务

  1. 创建一个新的接口和实现:

    cs 复制代码
    ​
    public interface IMyService
    {
        void DoWork();
    }
    
    public class MyService : IMyService
    {
        public void DoWork()
        {
            // 自定义逻辑,例如调用 API 或处理数据库操作
            Console.WriteLine("MyService is working...");
        }
    }
    
    ​
  2. Program.cs 中注册该服务:

    cs 复制代码
    services.AddTransient<IMyService, MyService>();
  3. Worker.cs 中使用该服务:

    cs 复制代码
    private readonly IMyService _myService;
    
    public Worker(ILogger<Worker> logger, IMyService myService)
    {
        _logger = logger;
        _myService = myService;
    }
    
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _myService.DoWork();
            _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }

8.2 配置管理

.NET Core 和 .NET 6 提供了强大的配置管理系统,可以通过 appsettings.json 文件或环境变量来进行配置管理。可以将配置注入到服务中以根据不同环境进行调整。

添加配置文件 appsettings.json

创建 appsettings.json 文件,并在其中添加所需的配置项,例如:

cs 复制代码
{
  "MyServiceConfig": {
    "Setting1": "Value1",
    "Setting2": "Value2"
  }
}

使用配置

Program.cs 中加载配置:

cs 复制代码
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((context, config) =>
        {
            config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
        })
        .ConfigureServices((hostContext, services) =>
        {
            services.Configure<MyServiceConfig>(hostContext.Configuration.GetSection("MyServiceConfig"));
            services.AddHostedService<Worker>();
            services.AddTransient<IMyService, MyService>();
        });

Worker.cs 中注入并使用配置:

cs 复制代码
public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IMyService _myService;
    private readonly IOptions<MyServiceConfig> _config;

    public Worker(ILogger<Worker> logger, IMyService myService, IOptions<MyServiceConfig> config)
    {
        _logger = logger;
        _myService = myService;
        _config = config;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Setting1: {setting1}", _config.Value.Setting1);
            _myService.DoWork();
            await Task.Delay(1000, stoppingToken);
        }
    }
}

public class MyServiceConfig
{
    public string Setting1 { get; set; }
    public string Setting2 { get; set; }
}

8.3 健康检查与监控

通过健康检查确保服务的正常运行。

  1. Program.cs 中添加健康检查支持:

    cs 复制代码
    services.AddHealthChecks();
  2. 实现自定义健康检查逻辑:

    cs 复制代码
    public class MyHealthCheck : IHealthCheck
    {
        public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            bool isHealthy = true; // 检查服务是否正常
            return isHealthy
                ? Task.FromResult(HealthCheckResult.Healthy("The service is healthy."))
                : Task.FromResult(HealthCheckResult.Unhealthy("The service is unhealthy."));
        }
    }
  3. Program.cs 中注册健康检查:

    cs 复制代码
    services.AddHealthChecks().AddCheck<MyHealthCheck>("My Health Check");

9. 日志持久化

将日志记录到文件、数据库或第三方日志管理系统。

  1. 安装 Serilog 的 NuGet 包:

    bash 复制代码
    dotnet add package Serilog.Extensions.Logging
    dotnet add package Serilog.Sinks.File
  2. Program.cs 中配置 Serilog:

    cs 复制代码
    using Serilog;
    
    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseSerilog((context, config) =>
            {
                config.WriteTo.Console();
                config.WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day);
            })
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
            });

10. 容器化支持

使用 Docker 将服务容器化,便于部署。

10.1 创建 Dockerfile

在项目的根目录下创建一个 Dockerfile

cs 复制代码
# 使用官方的 .NET SDK 镜像作为构建阶段
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /app

# 复制并构建应用程序
COPY . .
RUN dotnet restore
RUN dotnet publish -c Release -o out

# 使用 .NET 运行时镜像作为运行阶段
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build /app/out .

# 启动服务
ENTRYPOINT ["dotnet", "MyCrossPlatformService.dll"]

10.2 构建和运行 Docker 镜像

  1. 在 Visual Studio 中打开命令提示符,构建 Docker 镜像:

    bash 复制代码
    docker build -t mycrossplatformservice .
  2. 运行容器:

    bash 复制代码
    docker run -d --name mycrossplatformservice mycrossplatformservice

11. 总结

通过使用 Visual Studio 2022 和 .NET 6,您可以轻松创建一个跨平台的后台服务,支持 Windows、Linux 和 macOS。通过添加依赖注入、健康检查、日志记录和容器化等功能,您可以构建出复杂且高可维护性的跨平台服务。这使得 C# 和 .NET 6 成为构建现代背景服务的理想技术栈。您可以根据需求进一步扩展服务功能,例如数据库连接、API 集成、消息队列等,满足不同业务需求。

相关推荐
神仙别闹20 分钟前
基于C#+Mysql实现(界面)企业的设备管理系统
开发语言·mysql·c#
Neo Wordsworth37 分钟前
通义灵码在Visual Studio上
windows·ai·visual studio
悟空不是猴子1 小时前
VS Code终端命令执行后老是出现 __vsc_prompt_cmd_original: command not found
windows·vscode·prompt·bash
Flame_Cyclone2 小时前
FakerInput 键盘鼠标输入封装
c++·windows·win32·fakerinput
职业演员2 小时前
win11优化之win11取消二级菜单
windows
界面开发小八哥3 小时前
DevExpress WPF中文教程:如何解决排序、过滤遇到的常见问题?(二)
.net·wpf·界面控件·devexpress·ui开发
平凡而伟大(心之所向)4 小时前
关于.net Framework向.net core的移植
java·.net·.netcore
△曉風殘月〆4 小时前
.Net Gacutil工具(全局程序集缓存工具)使用教程
c#·.net·gac·gacutil
时光追逐者4 小时前
C#/.NET/.NET Core技术前沿周刊 | 第 5 期(2024年9.9-9.15)
microsoft·c#·.net·.netcore
太陈抱不动7 小时前
C#学习笔记(三)Visual Studio安装与使用
笔记·学习·c#