簡體   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