.NET Core 程序实现 Windows 系统 Development、Staging、Production 三种环境的无感部署

net,core,程序实现,windows,系统,development,staging,production,三种,环境,无感,部署 · 浏览次数 : 960

小编点评

## Summary of the Configuration Process This document outlines a comprehensive approach to dynamically configure your .NET Core WebAPI project based on its environment (Development, Staging, and Production). **Configuration Steps:** 1. **Create Three Configuration Files:** - `appsettings.Development.json` - `appsettings.Staging.json` - `appsettings.Production.json` 2. **Load Configuration Data:** - Read the configuration data within the controller's constructor using `IConfigurationRoot`. - Utilize `IConfigurationBuilder` for different environments. 3. **Configuration Based on Environment:** - Set the `ASPNETCORE_ENVIRONMENT` environment variable during development. - Use IIS configuration for the `IIS Express` service. 4. **Running Multiple Services on the Same Server:** - Modify `Startup.cs` to specify the desired environment (Development, Staging, or Production). - Configure environment-specific settings within the `Configure()` method. **Additional Configuration Details:** - Use `AppConfigure` class to manage and retrieve configurations. - `appsettings.json` holds the base configuration, while `appsettings.{environment}.json` overrides with environment-specific values. - Windows server configuration is achieved through environment variables. **Benefits of this Approach:** - **Dynamic Configuration:** Adapts to different environment needs. - **Code Maintainability:** Separates concerns and promotes modularity. - **Explicit Configuration:** Provides clarity and transparency. **Points to Consider:** - This approach utilizes multiple files for configuration, which might be considered complex. - Ensure proper error handling and logging for configuration issues. - Consider using a configuration management tool for easier configuration and version control.

正文

〇、前言

日常开发中,程序的环境切换是相当频繁的了,如果不同环境中的某些参数不同,那就需要每次编辑之前手动进行修改,比较麻烦,效率低下。

本文将以 .NET Core WebAPI 项目的配置方法为例,分步骤实现根据环境变量的配置参数,自动读取对应配置文件中的特殊参数值,从而达到 Development、Staging、Production 三种环境的无感部署。

一、配置文件

程序一般默认只有一个配置文件:appsettings.Development.json。

需要手动添加另外两个:appsettings.Staging.json、appsettings.Production.json。

 原配置文件中,默认只有一个节点:Logging,如下:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

 需要手动添加一个与 Logging 同级的节点,名称自定义,如下示例:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "MyPara": {
    "myparavalue": "测试文本",
    "myparavalue2": [
      {
        "key": "111",
        "value": "v111"
      },
      {
        "key": "222",
        "value": "v222"
      },
      {
        "key": "333",
        "value": "v333"
      }
    ]
  }
}

注意,三个配置文件中需要加上完全一样的参数名称,然后根据环境不同配置不同的值。

二、程序读取配置

1. 配置文件信息读取实现

接下来就是在程序中配置读取了,在控制器的构造函数添加环境判断,然后取出配置文件中新增节点的值备用。

以下实例,包含了读取 字符值、列表值 两种:

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;

[Route("api/[controller]/[action]")]
[ApiController]
public class SystemConfigController : ControllerBase // SystemConfig
{
    public static IConfigurationRoot configurationRoot = null;
    // 示例只有两个字段,就用字典 Dictionary 来演示了,若字段较多时,可用实体对象 list
    public static Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
    public SystemConfigController(IWebHostEnvironment env)
    {
        try
        {
            configurationRoot = AppConfigure.GetConfigurationRoot(env.ContentRootPath, env.EnvironmentName);
            if (keyValuePairs.Count == 0) // 仅首次加载时读取
            {
                string flag = string.Empty;
                int i = 0;
                while (flag != null)
                {
                    var keyinfo = configurationRoot[$"MyConfigPara:myparavalue2:{i}:key"];
                    var valueinfo = configurationRoot[$"MyConfigPara:myparavalue2:{i}:value"];
                    if (keyinfo != null && valueinfo != null)
                    {
                        keyValuePairs.Add(keyinfo, valueinfo); // 加入字典
                        i++;
                    }
                    else
                        flag = null;
                }
            }
        }
        catch (Exception ex)
        {
            // 日志框架记录日志
        }
    }
    public void TestAction()
    {
        // 读取配置文件具体值
        string myparavalue = configurationRoot["MyPara:myparavalue"];
    }
}

配置文件读取帮助类:AppConfigure.cs。

using Microsoft.Extensions.Configuration;
using System.Collections.Concurrent;

public static class AppConfigure
{
    // 缓存字典
    private static readonly ConcurrentDictionary<string, IConfigurationRoot> _cacheDict;
    static AppConfigure()
    {
        _cacheDict = new ConcurrentDictionary<string, IConfigurationRoot>();
    }
    // 传入 JSON 文件夹路径与当前的环境变量值
    public static IConfigurationRoot GetConfigurationRoot(string jsonDir, string environmentName = null)
    {
        // 设置缓存的 KEY
        var cacheKey = $"{jsonDir}#{environmentName}";
        // 添加默认的 JSON 配置
        var builder = new ConfigurationBuilder().SetBasePath(jsonDir)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
        // 根据环境变量添加相应的 JSON 配置文件
        if (!string.IsNullOrEmpty(environmentName))
        {
            builder = builder.AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true);
        }
        // 返回构建成功的 IConfigurationRoot 对象
        return builder.Build();
    }
}

2. 关于本机测试

可以通过修改项目的初始设置文件(文件夹下 Properties-->launchSettings.json)修改当前的运行环境,也可以在项目属性的“Debug”中修改,效果是一样的,如下:

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:40493",
      "sslPort": 44360
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development" // 修改切换运行环境:Development、Production、Staging
      }
    },
    "Finance.ReconciliationPlatform": {
      "commandName": "Project",
      "dotnetRunMessages": "true",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

  

注意:launchSettings.json 文件,仅用于本地开发计算机,不会被编译发布到生产环境,因此不能存储重要信息。

三、Windows 服务器配置

最后就是配置 Windows 服务器的环境变量了,用来标识程序运行的环境。

如下图,根据需要配置不同的环境变量:

  • ASPNETCORE_ENVIRONMENT:Development
  • ASPNETCORE_ENVIRONMENT:Staging
  • ASPNETCORE_ENVIRONMENT:Production

注意:此方法配置的是服务器的环境变量,针对的是整台机器的环境类型,若需求是在同一台机器上配置多类型的程序,请参考后边章节。

至此,就配置完成了。

四、如何在同一台服务器 部署 两种不同环境 的服务?

1、修改 Startup.cs 代码,固定运行环境

通过在 Startup.cs 文件的 Configure() 方法中,赋值环境名称(EnvironmentName),以实现灵活控制程序的环境。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    env.EnvironmentName = "Production";
    if (env.IsProduction()) // true
    {
        // 。。。
    }
}

2、通过 IIS 配置服务的环境变量

通过 IIS 配置环境变量,也是区分生效范围的:

  • 若直接在根目录的“配置编辑器”中配置,则其下的服务将是同一环境类型;(后续更新服务后值不变)
  • 若针对单个服务的“配置编辑器”配置,则仅针对当前服务。(缺点:每次服务更新后,需重新配置)

注意,针对服务的环境配置优先级,高于根目录的配置。继承来的环境配置无法修改,要配置其他的环境,需要新增。

如下配置步骤:

(配置管理器 --> 根据路径查找 system.webServer/aspNetCore --> system.webServer/aspNetCore --> 编辑项ASPNETCORE_ENVIRONMENT填入指定的环境值Production、Staging、Development

项路径中另加服务名称的就是在当前服务新增的,另外一个则是从根目录继承来的,当前新增的优先级较高。

与.NET Core 程序实现 Windows 系统 Development、Staging、Production 三种环境的无感部署相似的内容:

.NET Core 程序实现 Windows 系统 Development、Staging、Production 三种环境的无感部署

本文将以 .NET Core WebAPI 项目的配置方法为例,分步骤实现根据环境变量的配置参数,自动读取对应配置文件中的特殊参数值,从而达到 Development、Staging、Production 三种环境的无感部署。

XUnit数据共享与并行测试

引言 在单元或者集成测试的过程中,需要测试的用例非常多,如果测试是一条一条过,那么需要花费不少的时间。从 V2 开始,默认情况下 XUnit 自动配置并行(参考资料),大大提升了测试速度。本文将对 ASP.NET CORE WEBAPI 程序进行集成测试,并探讨 XUnit 的数据共享与测试并行的方

如何将WebAssembly优化到1MB?

Blazor WebAssembly加载优化方案 对于Blazor WebAssembly加载方案的优化是针对于WebAssembly首次加载,由于BlazorWebAssembly是在首次加载的时候会将.NET Core的所有程序集都会加载到浏览器中,并且在使用的时候可能引用了很多第三方的dll,

Asp-Net-Core开发笔记:使用原生的接口限流功能

前言 之前介绍过使用 AspNetCoreRateLimit 组件来实现接口限流 从 .Net7 开始,AspNetCore 开始内置限流组件,当时我们的项目还在 .Net6 所以只能用第三方的 现在都升级到 .Net8 了,当然是得来试试这个原生组件 体验后:配置使用都比较简单,不过功能也没有 A

Asp-Net-Core开发笔记:给SwaggerUI加上登录保护功能

前言 在 SwaggerUI 中加入登录验证,是我很早前就做过的,不过之前的做法总感觉有点硬编码,最近 .Net8 增加了一个新特性:调用 MapSwagger().RequireAuthorization 来保护 Swagger UI ,但官方的这个功能又像半成品一样,只能使用 postman c

Asp-Net-Core开发笔记:使用ActionFilterAttribute实现非侵入式的参数校验

前言 在现代应用开发中,确保API的安全性和可靠性至关重要。 面向切面编程(AOP)通过将横切关注点(如验证、日志记录、异常处理)与核心业务逻辑分离,极大地提升了代码的模块化和可维护性。 在ASP.NET Core中,利用ActionFilterAttribute可以方便地实现AOP的理念,能够以简

Asp-Net-Core开发笔记:进一步实现非侵入性审计日志功能

前言 上次说了利用 AOP 思想实现了审计日志功能,不过有同学反馈还是无法实现完全无侵入,于是我又重构了一版新的。 回顾一下:Asp-Net-Core开发笔记:实现动态审计日志功能 现在已经可以实现对业务代码完全无侵入的审计日志了,在需要审计的接口上加上 [AuditLog] 特性,就可以记录这个接

Asp-Net-Core开发笔记:EFCore统一实体和属性命名风格

前言 C# 编码规范中,类和属性都是大写驼峰命名风格(PascalCase / UpperCamelCase),而在数据库中我们往往使用小写蛇形命名(snake_case),在默认情况下,EFCore会把原始的类名和属性名直接映射到数据库,这不符合数据库的命名规范。 为了符合命名规范,而且也为了看起

Asp-Net-Core开发笔记:快速在已有项目中引入EFCore

前言 很多项目一开始选型的时候没有选择EFCore,不过EFCore确实好用,也许由于种种原因后面还是需要用到,这时候引入EFCore也很方便。 本文以 StarBlog 为例,StarBlog 目前使用的 ORM 是 FreeSQL ,引入 EFCore 对我来说最大的好处是支持多个数据库,如果是

Asp-Net-Core开发笔记:使用RateLimit中间件实现接口限流

前言 最近一直在忙(2月份沉迷steam,3月开始工作各种忙),好久没更新博客了,不过也积累了一些,忙里偷闲记录一下。 这个需求是这样的,我之前做了个工单系统,现在要对登录、注册、发起工单这些功能做限流,不能让用户请求太频繁。 从 .Net7 开始,已经有内置的限流功能了,但目前我们的项目还在使用