.NET Core 程式實現 Windows 系統 Development、Staging、Production 三種環境的無感部署

2023-06-02 12:00:28

〇、前言

日常開發中,程式的環境切換是相當頻繁的了,如果不同環境中的某些引數不同,那就需要每次編輯之前手動進行修改,比較麻煩,效率低下。

本文將以 .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"
      }
    ]
  }
}

注意,三個組態檔中需要加上完全一樣的引數名稱,然後根據環境不同設定不同的值。

二、程式讀取設定

接下來就是在程式中設定讀取了,在控制器的建構函式新增環境判斷,然後取出組態檔中新增節點的值備用。

以下範例,包含了讀取 字元值、列表值 兩種:

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

三、Windows 伺服器設定

最後就是設定 Windows 伺服器的環境變數了,用來標識程式執行的環境。

如下圖,根據需要設定不同的環境變數:

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

  

至此,就設定完成了。

注意:如果設定完環境變數還是不能讀取指定的設定,可以參考下這個:https://blog.csdn.net/lilinoscar/article/details/108362211