繁体   English   中英

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

[英]Azure functions host.json somehow being ignored

我有一个 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] 队列选项

[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 规范

我遇到了与 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;
}

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

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

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


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

设想

  • 函数 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;
}

我希望这对某人有帮助

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM