【问题标题】:Azure Functions, how to have multiple .json config filesAzure Functions,如何拥有多个 .json 配置文件
【发布时间】:2019-10-20 18:17:55
【问题描述】:

所以我编写了一个在本地运行良好的天蓝色函数。我相信这取决于拥有local.setting.json 文件。但是当我将它发布到天蓝色时,该功能不起作用,因为它找不到我定义的设置值。来自 Web 应用程序和控制台驱动的方法,我们将拥有与每个环境相关联的不同配置文件。我怎样才能让它工作,这样我就可以拥有多个 settings.json 文件,例如一个用于开发、雄鹿和产品环境?最终结果是使用 octopus deploy 来部署它,但在这一点上,如果我什至不能让它与发布一起工作,那么就没有机会这样做了。

我很困惑为什么这些信息不容易获得,因为假设这是一种常见的事情?

【问题讨论】:

  • 一种正确的方法是在您的应用程序部署期间将它们添加为 ARM 模板,以便它们出现在您的 Function App -> configuration -> Application Settings 中。由于每个环境有不同的模板,您可以改变每个模板的变量。

标签: c# azure azure-functions asp.net-core-2.0


【解决方案1】:

好的,我现在可以使用它了 :) 因为我们使用 octopus deploy,所以我们不想要多个配置文件,所以我们只有一个 appsettings.Release.json 文件,它可以获取替换的值 base在正在部署的环境上。

以下是主要功能代码。

public static class Function
    {
        // Format in a CRON Expression e.g. {second} {minute} {hour} {day} {month} {day-of-week}
        // https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-timer
        // [TimerTrigger("0 59 23 * * *") = 11:59pm
        [FunctionName("Function")]
        public static void Run([TimerTrigger("0 59 23 * * *")]TimerInfo myTimer, ILogger log)
        {

            // If running in debug then we dont want to load the appsettings.json file, this has its variables substituted in octopus
            // Running locally will use the local.settings.json file instead
#if DEBUG
            IConfiguration config = new ConfigurationBuilder()
                .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables()
                .Build();
#else
            IConfiguration config = Utils.GetSettingsFromReleaseFile();
#endif

            // Initialise dependency injections
            var serviceProvider = Bootstrap.ConfigureServices(log4Net, config);

            var retryCount = Convert.ToInt32(config["RetryCount"]);

            int count = 0;
            while (count < retryCount)
            {
                count++;
                try
                {
                    var business = serviceProvider.GetService<IBusiness>();
                    business.UpdateStatusAndLiability();
                    return;
                }
                catch (Exception e)
                {
                    // Log your error
                }
            }

        }

    }

Utils.cs 文件如下所示

public static class Utils
    {

        public static string LoadSettingsFromFile(string environmentName)
        {
            var executableLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            // We need to go back up one level as the appseetings.Release.json file is not put in the bin directory
            var actualPathToConfig = Path.Combine(executableLocation, $"..\\appsettings.{environmentName}.json");
            using (StreamReader reader = new StreamReader(actualPathToConfig))
            {
                return reader.ReadToEnd();
            }
        }

        public static IConfiguration GetSettingsFromReleaseFile()
        {
            var json = Utils.LoadSettingsFromFile("Release");
            var memoryFileProvider = new InMemoryFileProvider(json);

            var config = new ConfigurationBuilder()
                .AddJsonFile(memoryFileProvider, "appsettings.json", false, false)
                .Build();
            return config;
        }

    }

appsettings.Release.json 在 Visual Studio 中设置为 ContentCopy Always。看起来是这样的

{
  "RetryCount": "#{WagonStatusAndLiabilityRetryCount}",
  "RetryWaitInSeconds": "#{WagonStatusAndLiabilityRetryWaitInSeconds}",
  "DefaultConnection": "#{YourConnectionString}"
}

实际上,我相信您可能已经有一个 appsettings.config 文件并跳过 appsettings.Release.json 文件,但这是有效的,您现在可以用它做您想做的事。

【讨论】:

  • 我看不出你从哪里得到这个类:InMemoryFileProvider 来自。
  • 我想它类似于stackoverflow.com/a/52405277/277067,我没有可用的代码。同样谷歌搜索“ConfigurationBuilder addjsonfile in memory”返回相同的页面stackoverflow.com/questions/44807836/…
  • 即便如此,我也很难让我的个人项目加载我添加到项目中的 json 文件。我有一个设置文件,我希望数据库项目加载它。 dbAppsettings 是我在运行 API 时想要加载的文件,并且有一个用于解析 Web API 对象的设置文件。
【解决方案2】:

我希望看到函数以与 asp.net 核心或控制台应用程序相同的方式支持特定于环境的设置。与此同时,我正在使用下面的代码,这有点 hacky(见 cmets)。

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        // Get the path to the folder that has appsettings.json and other files.
        // Note that there is a better way to get this path: ExecutionContext.FunctionAppDirectory when running inside a function. But we don't have access to the ExecutionContext here.
        // Functions team should improve this in future. It will hopefully expose FunctionAppDirectory through some other way or env variable.
        string basePath = IsDevelopmentEnvironment() ?
            Environment.GetEnvironmentVariable("AzureWebJobsScriptRoot") :
            $"{Environment.GetEnvironmentVariable("HOME")}\\site\\wwwroot";

        var config = new ConfigurationBuilder()
            .SetBasePath(basePath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: false)  // common settings go here.
            .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT")}.json", optional: false, reloadOnChange: false)  // environment specific settings go here
            .AddJsonFile("local.settings.json", optional: true, reloadOnChange: false)  // secrets go here. This file is excluded from source control.
            .AddEnvironmentVariables()
            .Build();

        builder.Services.AddSingleton<IConfiguration>(config);
    }

    public bool IsDevelopmentEnvironment()
    {
        return "Development".Equals(Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT"), StringComparison.OrdinalIgnoreCase);
    }
}

【讨论】:

  • 是的,这与我正在做的类似,但使用 octopus deploy 我将有一个 json 文件,希望将配置值注入其中,因此将放置 dev、stag 和 prod 的相关值.上述方法是我所拥有的,但想让它与我们的 octopus deploy 版本更兼容。
  • 在此基础上,您可以访问ExecutionContextOptions,如下所示:builder.Services.BuildServiceProvider().GetService&lt;IOptions&lt;ExecutionContextOptions&gt;&gt;().Value;
【解决方案3】:

这个文档有description 关于local.settings.json

默认情况下,这些设置不会在 项目已发布到 Azure。

一种方法是使用--publish-local-settings

将 local.settings.json 中的设置发布到 Azure,提示 如果设置已存在,则覆盖。

另一种方法是使用Manage Application SettingsRemote 是 Azure 函数应用中的当前设置。或选择添加设置以创建新的应用设置。具体可以参考这个文档:Function app settings

【讨论】:

  • 是的,可能有一些工作需要确认,而不是热衷于发布本地设置文件。应用程序设置似乎也没有为所有环境提供足够的选项。我很快就会发布我的解决方案,干杯
  • @Andrew,如果您使用 Azure Functions Core Tools,您可以使用 --publish-local-settings 确保将这些设置添加到 Azure 中的函数应用。但如果没有,是的,您必须手动添加它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多