Azure函数host.json以某种方式被忽略

时间:2019-05-27 12:51:56

标签: azure azure-functions

我具有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]构建主机:禁止启动:错误,配置   抑制:错误

     

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

     

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

     

...

     

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

     

[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

的引用

4 个答案:

答案 0 :(得分:5)

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

正如jsgoupil在Dave的帖子中所述,ImplementationInstance为null。这是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;
}

答案 1 :(得分:3)

似乎报告了here个未解决的问题,函数启动忽略了host.json

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

答案 2 :(得分:2)

I responded与github中报告的相同(或相似)问题有关。为了帮助其他人降落在这里,我在这里重新发布。


为落在此处的其他人添加更多信息。另外,由于我还没有看到其他人提到此内容,因此我可能在解释/做错了此事。如果是这样,请说出来。

场景

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

我观察到的情况

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

我的理论

似乎在注册同一服务的两个单例时,DI框架将仅获取最后添加的一个。

我的解决方案

我从IConfiguration中提取了现有的IServiceCollection提供者,并将其添加到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;
}

我希望这对某人有帮助

答案 3 :(得分:0)

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

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