【问题标题】:Azure functions host.json somehow being ignoredAzure 函数 host.json 以某种方式被忽略
【发布时间】:2019-05-27 12:51:56
【问题描述】:

我有一个 V2 Azure 功能。我已将此功能配置为仅并行运行一个功能。这是我的 host.json 文件:

{ "version": "2.0", "extensions": { "queues": { "batchSize": 1, "newBatchThreshold": 0 } } }

当我在本地开发机器上启动该功能时,它会显示以下输出:

[27-5-2019 12:43:06] 启动 Rpc 初始化服务。

[27-5-2019 12:43:06] 初始化 RpcServer

[27-5-2019 12:43:06] 构建主机:启动被抑制:False,配置 压制:假

[27-5-2019 12:43:07] 正在初始化主机。

[27-5-2019 12:43:07] 主机初始化:ConsecutiveErrors=0, StartupCount=1

...

[27-5-2019 12:43:07] 队列选项

[27-5-2019 12:43:07] {

[27-5-2019 12:43:07] “BatchSize”:16,

[27-5-2019 12:43:07] “NewBatchThreshold”:8,

[27-5-2019 12:43:07] "MaxPollingInterval": "00:00:02",

[27-5-2019 12:43:07] "MaxDequeueCount": 5,**

[27-5-2019 12:43:07] "VisibilityTimeout": "00:00:00"

在此输出之后,它似乎没有注册这些设置。该行为也显示了这一点,因为函数并行运行而不是一次运行一个。我究竟做错了什么?

感谢任何帮助。

参考 MS host.json specification

【问题讨论】:

  • 您使用的是 Azure 应用服务计划还是消费计划?
  • 消耗计划,但是这个例子是在开发中运行的。

标签: azure azure-functions


【解决方案1】:

我遇到了与 Dave Parker 完全相同的问题,他对覆盖 host.json 配置的新配置注册的分析非常准确。

正如 jsgoupil 在 Dave 的帖子中评论的那样,ImplementationInstance 为空。这里对 Dave 的代码进行了一些细微的更新来处理这个问题。


public IConfigurationRoot AddSettings(IServiceCollection services, string basePath, string name, bool optional, bool reloadOnChange)
{
    var builder = new ConfigurationBuilder().SetBasePath(basePath);

    // check if an IConfiguration has already been registered
    var existingConfig = builder.Services.FirstOrDefault(x => x.ServiceType.Name == nameof(IConfiguration));
    if(existingConfig != null)
    {
        // get an instance of it and include it in the new config builder
        var sp = builder.Services.BuildServiceProvider();
        var existingInstance = sp.GetService<IConfiguration>();
        builder.AddConfiguration(existingInstance);
    }

    // Register/load the requested json settings file
    builder.AddJsonFile(name, optional, reloadOnChange);

    // Add all environment vars and build the ConfigurationRoot object. Then register it with the services container
    builder.AddEnvironmentVariables();
    var config = builder.Build();

    // Register the resulting IConfigurationRoot to as a singleton
    services.AddSingleton<IConfiguration>(config);

    return config;
}

【讨论】:

  • 我遇到了同样的问题。配置丢失,因为我创建了一个新的空 ConfigurationBuilder,添加了 som json 配置并注册了它。添加运行时已经注册的配置就可以了!谢谢你尼克!
  • 这对我的问题有帮助。谢谢尼克。我认为,这应该默认处理。
【解决方案2】:

似乎报告了一个未解决的问题 here,Functions Startup 忽略了 host.json

如果您的代码中有[assembly: WebJobsStartup(typeof(Startup))],删除它应该可以正确识别host.json

【讨论】:

  • 所以这意味着我们要么没有 DI 要么没有 host.json,不是最好的情况。我暂时将其标记为答案,因为没有有效的替代方案
【解决方案3】:

responded 到 github 中报告的相同(或类似)问题。为了帮助其他人登陆这里,我在这里重新发布。


为其他登陆这里的人添加更多信息。另外,由于我没有看到其他人提到这一点,我可能在解释/做错了。如果是这样,请说出来。

场景

  • Functions v2 应用,SDK 1.0.29
  • C#
  • 使用[assembly: FunctionsStartup(typeof(Startup))]
  • 使用new ConfigurationBuilder(),添加我的配置内容
  • 将内置 IConfigurationRoot 注册为单例 IConfiguration

我观察到的

在添加我的IConfigurationRoot 之前设置断点并查看IServiceCollection 我可以看到已经注册了一个单例IConfiguration。此外,此实例中包含 host.json 的提供程序,但在 Azure 中运行时未加载。

我的理论

看起来,当注册同一服务的两个单例时,DI 框架只会抓取最后添加的一个。

我的解决方案

我从IServiceCollection 中提取了现有的IConfiguration 提供程序并将其添加到ConfigurationBuilder,以便它的值包含在我注册的ConfigurationRoot 中,因此被DI 框架获取。

代码

public IConfigurationRoot AddSettings(IServiceCollection services, string basePath, string name, bool optional, bool reloadOnChange)
{
    var builder = new ConfigurationBuilder().SetBasePath(basePath);

    var existingConfigs = services.Where(svc => svc.ServiceType.Name == "IConfiguration").ToList();
    foreach (var cfg in existingConfigs)
        builder.AddConfiguration((IConfigurationRoot) cfg.ImplementationInstance);

    // Register/load the requested json settings file
    builder.AddJsonFile(name, optional, reloadOnChange);

    // Add all environment vars and build the ConfigurationRoot object. Then register it with the services container
    builder.AddEnvironmentVariables();
    var config = builder.Build();

    // Register the resulting IConfigurationRoot to as a singleton
    services.AddSingleton<IConfiguration>(config);

    return config;
}

我希望这对某人有帮助

【讨论】:

  • 我认为这个想法就在那里,但这对我不起作用。也许我没有正确调用这个方法?我将builder.Services 作为第一个参数传递。这个构建器是IFunctionsHostBuilder。但是,然后cfg.ImplementationInstance 为空。还有什么技巧吗?
  • 我厌倦了 v3 中的 service.Replace,但它不起作用,尽管配置源中存在 HostJsonProvider
  • 有人可以展示如何实际使用此代码吗?
【解决方案4】:

非常感谢您!我使用了一个小的变化,因为我在启动期间利用工厂模式的延迟调用来引用配置:

public static IServiceCollection AddConfigurationFactory(this IServiceCollection services)
{
    var configurationEnvironment = Environment.GetEnvironmentVariable("ConfigEnv");
    var jsonConfigFilename = $"appsettings.{configurationEnvironment}.json";

#if DEBUG
    var basePath = Environment.CurrentDirectory;
#else
    var basePath = @"/home/site/wwwroot";  
#endif
    var existingConfig = services.FirstOrDefault(x => x.ServiceType.Name == 
        nameof(IConfiguration));
    IConfiguration existingInstance = null;
    if (existingConfig != null)
    {
        var spOuter = services.BuildServiceProvider();
        existingInstance = spOuter.GetService<IConfiguration>(); 
    }
    Func<IServiceProvider, IConfiguration> factory = (sp) =>
    {
        var configBuilder = new ConfigurationBuilder()
            .SetBasePath(basePath)
            .AddEnvironmentVariables()
            .AddJsonFile(jsonConfigFilename, optional: false, reloadOnChange: true);
                
        if (existingInstance != null)
            configBuilder.AddConfiguration(existingInstance);

        return configBuilder.Build();
    };
    services.AddSingleton<IConfiguration>(factory);
    return services;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-10-19
    • 2017-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    相关资源
    最近更新 更多