使用 .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 项目
- 启动 Visual Studio 2022。
- 点击 "创建新项目"。
- 在搜索框中输入 "Worker"。
- 选择 "Worker Service" 模板,点击 "下一步"。
- 输入项目名称(例如
MyCrossPlatformService
),选择位置并点击 "创建"。
此时,Visual Studio 将生成一个基本的 Worker Service 项目结构。
2. 项目结构
创建的项目结构如下:
MyCrossPlatformService/
├── MyCrossPlatformService.csproj
├── Program.cs
└── Worker.cs
3. 实现 Worker Service服务
3.1 编辑 Worker.cs
打开 Worker.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
中配置和启动应用:
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 中,可以直接使用调试工具运行服务:
- 点击菜单中的 "调试" > "开始调试"(或按 F5)。
- 控制台窗口将打开,并每秒记录当前时间。
5.2 在 Linux 上运行
要在 Linux 上运行此服务,您需要发布它并使用命令行运行。可以使用以下步骤:
- 在 Visual Studio 中右键单击项目,选择 “发布”。
- 选择目标(例如文件夹),设置输出路径,并选择发布配置(Release)。
- 点击 “发布”。
发布完成后,您可以将输出文件夹中的内容部署到 Linux 系统上,然后使用以下命令运行:
dotnet MyCrossPlatformService.dll
6. 部署为系统服务
在 Linux 上,可以将该应用注册为 systemd
服务以便于管理。
6.1 创建 systemd 服务文件
创建一个 systemd
服务文件,文件名为 /etc/systemd/system/mycrossplatformservice.service
,内容如下:
[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 启用和启动服务
执行以下命令启用并启动服务:
sudo systemctl enable mycrossplatformservice
sudo systemctl start mycrossplatformservice
6.3 检查服务状态
您可以使用以下命令检查服务的状态:
sudo systemctl status mycrossplatformservice
7. 日志记录
7.1 配置日志记录
在 Worker 中,我们使用了 ILogger<Worker>
来记录信息。在 Visual Studio 中,您可以通过 appsettings.json
文件配置日志记录设置。例如:
{"Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"}},"AllowedHosts": "*"
}
我们也可以使用log4net、NLog等第三方日志库来记录日志,尤其是log4net非常的强大,具体使用在此不进行具体介绍,因为网络上资源很多了。
8. 高级特性与扩展
在完成基本服务后,可以通过以下方式进一步增强服务的功能和可维护性:
8.1 使用依赖注入
您可以通过依赖注入来实现服务间的解耦。
添加自定义服务
- 创建一个新的接口和实现:
public interface IMyService {void DoWork(); }public class MyService : IMyService {public void DoWork(){// 自定义逻辑,例如调用 API 或处理数据库操作Console.WriteLine("MyService is working...");} }
- 在
Program.cs
中注册该服务:services.AddTransient<IMyService, MyService>();
- 在
Worker.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
文件,并在其中添加所需的配置项,例如:
{"MyServiceConfig": {"Setting1": "Value1","Setting2": "Value2"}
}
使用配置
在 Program.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
中注入并使用配置:
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 健康检查与监控
通过健康检查确保服务的正常运行。
- 在
Program.cs
中添加健康检查支持:services.AddHealthChecks();
- 实现自定义健康检查逻辑:
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."));} }
- 在
Program.cs
中注册健康检查:services.AddHealthChecks().AddCheck<MyHealthCheck>("My Health Check");
9. 日志持久化
将日志记录到文件、数据库或第三方日志管理系统。
- 安装 Serilog 的 NuGet 包:
dotnet add package Serilog.Extensions.Logging dotnet add package Serilog.Sinks.File
- 在
Program.cs
中配置 Serilog: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
:
# 使用官方的 .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 镜像
- 在 Visual Studio 中打开命令提示符,构建 Docker 镜像:
docker build -t mycrossplatformservice .
- 运行容器:
docker run -d --name mycrossplatformservice mycrossplatformservice
11. 总结
通过使用 Visual Studio 2022 和 .NET 6,您可以轻松创建一个跨平台的后台服务,支持 Windows、Linux 和 macOS。通过添加依赖注入、健康检查、日志记录和容器化等功能,您可以构建出复杂且高可维护性的跨平台服务。这使得 C# 和 .NET 6 成为构建现代背景服务的理想技术栈。您可以根据需求进一步扩展服务功能,例如数据库连接、API 集成、消息队列等,满足不同业务需求。
相关文章:

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

terminator-gnome
gnome import os#启动节点指令变量 stere"ros2 launch stereo_c start.py" utils"ros2 launch task utils.launch.py" #tab标题 stere_title"stere_driver" utils_title"utils"#一个终端界面打开5个tab cmd1f"gnome-terminal --…...
7.测试用例设计方法 + Bug
一、正交实验法 1.使用场景 因果关系比较庞大的情况下,不太适合用因果图判定表,在这种情况下,一般会采用正交实验法。 2.例子: 字符属性设置(4个条件) 字体很多 字符样式很多 …...

uniapp小程序,使用腾讯地图获取定位
本篇文章分享一下在实际开发小程序时遇到的需要获取用户当前位置的问题,在小程序开发过程中经常使用到获取定位功能。uniapp官方也提供了相应的API供我们使用。 官网地址:uni.getLocation(OBJECT)) 官网获取位置的详细介绍这里就不再讲述了,大…...

Reactive 编程-Project Reactor
Reactive 编程与 Project Reactor Reactive 编程是一种编程范式,主要用于处理异步数据流。它旨在通过声明式的编程方式处理事件驱动的非阻塞任务,特别适合于构建响应式、可扩展、高并发的应用。随着互联网应用规模的扩大和响应速度的提升需求࿰…...

splice用法
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...

Redis - 缓存
文章目录 目录 文章目录 1. 什么是缓存? 2. 使用Redis作为缓存 2.1 关系型数据库的缺点 3. 缓存的更新策略 3.1 定期生成 3.2 实时生成 缓存淘汰策略 4. 缓存预热, 缓存穿透, 缓存雪崩 和 缓存击穿 缓存预热 缓存穿透 缓存雪崩 缓存击穿 总结 1. 什么…...

基于SpringBoot+Vue的养老院管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…...

多线程爬虫接入代理IP:高效数据抓取的秘诀
在现代网络环境中,爬虫已经成为获取信息的利器。然而,随着网站反爬措施的不断升级,单线程爬虫往往无法满足需求。多线程爬虫与代理IP的结合,不仅能提高效率,还能有效规避IP封禁问题。本文将详细探讨多线程爬虫接入代理…...

[网络][CISCO]Cisco-PIX配置详解
Cisco PIX防火墙配置指南 任何企业安全策略的一个主要部分都是实现和维护防火墙,因此防火墙在网络安全的实现当中扮演着重要的角色。防火墙通常位于企业网络的边缘,使内部网络与Internet之间或与其他外部网络互相隔离,并限制网络互访&#x…...

拒绝千篇一律,AI帮你定制独一无二的个人写真
每个女人都渴望展现最美的自己,你是否厌倦了拍出千篇一律的照片?今天,我要告诉你一个秘密,用简单三步,即可打造属于你的独一无二个人写真!文生图、蒙版换脸、图生图,三步化身超级模特࿰…...

在云服务器上安装 RabbitMQ:从零到一的最佳实践
🛠 1. RabbitMQ 简介 RabbitMQ 是一个开源的消息代理中间件,广泛应用于高并发、异步任务队列的场景中。在分布式系统架构中,RabbitMQ 可以充当消息的中转站,帮助不同服务之间进行高效的消息通信。 在这篇文章中,我们…...

【nginx】搭配okhttp 配置反向代理
nginx的默认是一个反向代理。 nginx会默认把输入的请求,转向其他的服务器执行。 这些转向的服务器与客户端发起的服务器不是同一个。 客户端只认识nginx,不知道ngiix转向何方。 正向代理修改okhttp的proxy,实际上很多代理都是正向的。 反向代理修改请求路径到nginx。 感觉还…...

Android V 广播注册和配置注意事项问题
现象 在Android V平台上,应用注册非Protected广播时,如果没有加导出flag会抛出异常导致进程crash。 E/AndroidRuntime: FATAL EXCEPTION: main java.lang.SecurityException: com.demo.myapplication: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORT…...

深入解读Docker核心原理:Namespace资源隔离机制详解
在容器技术中,资源隔离 是容器化能够实现轻量级虚拟化的关键技术之一。通过资源隔离,容器可以拥有自己的独立环境,确保容器之间互不干扰,从而实现应用的安全和稳定。Docker作为主流的容器平台,其核心的资源隔离机制依赖…...

学习通、智慧职教刷课脚本
🐐个人主页 可惜已不在 🐋可以分享给身边有需要的人🐶 🐉有用的话就留下一个三连吧😼 目录 一.安装 脚本运行器 篡改猴 - Microsoft Edge Addons 二.安装脚本 三.扩展 一.安装 脚本运行器 安装浏览器 Microsoft E…...

SEO写作:从实战到精进的全方位指南
在数字化浪潮中,SEO不再是简单的关键词堆砌,而是成为企业品牌建设与市场拓展的核心策略。作为一名深耕SEO领域的实践者,我深知其中的门道与奥秘。今天,我将结合过往实战经验,以独特视角,带你一窥SEO写作的精…...

解决 git 不是内部或外部命令,也不是可运行的程序
目录 报错提示: 一、解决办法 1、从git官网下载windows版本的git 2、安装 3、注意事项 二、报错 1、解决 fatal: Not a git repository (or any of the parent directories): .git 问题 报错提示: 一、解决办法 Windows下配置Git: 1…...

【卷起来】VUE3.0教程-07-异步请求处理(springboot后端)
🌲 服务端接口准备 pom文件,引入mybatis/mybatis-plus相关依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>&…...

初一信息科技2024指南辅助教学软件(抓包软件)
专门针对信息科技20204指南写的程序,互联网和直播等知识中包含tcp/ip和udp,三次握手等原理,需要简单明了的实验来说明,在机房中需要用抓包软件,可能需要安装windump npcap等软件非常繁琐,还需要接触保护卡&…...

上汽大众:存储成本节约85%,查询性能提升5倍|OceanBase案例
近日,上汽大众汽车有限公司(简称“上汽大众”)的积分卡券等关键业务系统,已成功升级至 OB Cloud 云数据库。借助 OceanBase 原生分布式数据库的卓越性能与先进技术,实现了存储成本的大幅降低,高达85%&#…...

如何快准稳 实现MySQL大表历史数据迁移?
历史迁移解决方案以微服务架构为基础,使用多种设计模式,如:单例、桥接、工厂、模板、策略等。其中涉及的核心技术有多线程、过滤器等,致力于解决MySQL大表迁移的问题,提供多种迁移模式,如:库到库…...

C和指针:函数
函数定义 函数体就是一个代码块,它在函数被调用时执行。 类型 函数名(形式参数) 代码块 与函数定义相反,函数声明出现在函数被调用的地方。 函数声明 编译器是如何知道该函数期望接受的是什么类型和多少数量的参数。 原型 int *find_int( int key…...

Linux——分离部署,分化压力
PQS/TPS 每秒请求数/ 每秒事务数 // 流量衡量参数 可以根据预估QPS 和 服务器的支持的最高QPS 对照计算 就可以得出 需要上架的服务器的最小数量 PV 页面浏览数 UV 独立用户访问量 // 对于网站的总体访问量 response time 响应时间 // 每个请求的响应时间…...

javaaaa
1 飞机票 代码实现: import java.util.Scanner; public class F1 {public static void main(String[] args) {Scanner input new Scanner(System.in);System.out.print("请输入票价: ");double jia input.nextDouble();System.out.print(&…...

游戏开发引擎___unity位置信息和unlit shader(无光照着色器)的使用,以桌子的渲染为例
unity是左手坐标系 1.位置信息 1.1 代码 using System.Collections; using System.Collections.Generic; using UnityEngine;public class positionTest : MonoBehaviour {public Camera Camera;private void OnGUI(){//世界坐标系,GUI里的标签GUI.Label(new Rec…...

反向沙箱的功能特点
在这个信息化飞速发展的时代,企业的数据安全面临着前所未有的挑战。员工的无意操作、恶意软件的潜伏、甚至是敌对势力的网络攻击,都可能成为企业数据安全的致命威胁。深信达SPN反向沙箱为您筑起了一道坚不可摧的数据安全防线! 来百度APP畅享高…...

可测试,可维护,可移植:上位机软件分层设计的重要性
互联网中,软件工程师岗位会分前端工程师,后端工程师。这是由于互联网软件规模庞大,从业人员众多。前后端分别根据各自需求发展不一样的技术栈。那么上位机软件呢?它规模小,通常一个人就能开发一个项目。它还有必要分前…...

构造函数与析构函数的执行顺序
对象作为成员变量的构造函数与析构函数 当一个类包含另一个类的对象作为成员时,这些成员对象的构造函数会在包含它们的对象的构造函数之前被调用,而它们的析构函数则会在包含它们的对象的析构函数之后被调用。成员对象的构造函数和析构函数的调用顺序与…...

Vue框架;Vue中的选择和循环结构;Vue数据类型;Vue中的事件和动态属性;Vue子组件通过导入在主组件显示在网页;Vue中主组件向子组件传递数据
一,Vue简介 前端现在比较火的三大框架就是:vue ,React,Angular。在国内使用最多的还是: vue >React >Angular Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准…...