在dotnet核心中读取json文件时出错"已达到inotify实例数量的已配置用户限制(128)"

Vip*_*pin 8 c# .net-core asp.net-core .net-standard

我有一个控制台应用程序(在网络核心1.1中),它每隔1分钟在cron调度程序中安排一次.在应用程序内部有调用配置文件.我附上下面的代码.

public static T GetAppConfig<T>(string key, T defaultValue = default(T))
{

    T value = default(T);
    logger.Debug($"Reading App Config {key}");
    try
    {
        var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        var builder = new ConfigurationBuilder()
            .AddJsonFile($"appsettings.json", true, true)
            .AddJsonFile($"appsettings.{environmentName}.json", true, true)
            .AddEnvironmentVariables();
        var configuration = builder.Build();
        T setting = (T)Convert.ChangeType(configuration[key], typeof(T));
        value = setting;
        if (setting == null)
            value = defaultValue;
    }
    catch (Exception ex)
    {
        logger.Warn(ex, $"An exception occured reading app key {key} default value {defaultValue} applied.");
        value = defaultValue;
    }
    return value;
}
Run Code Online (Sandbox Code Playgroud)

在运行应用程序一段时间之后,此错误将在我的日志文件中获得"已达到inotify实例数量的已配置用户限制(128)".请找到完整的堆栈跟踪.

An exception occured reading app key DeviceId default value  applied.
System.IO.IOException: The configured user limit (128) on the number of inotify instances has been reached.
   at System.IO.FileSystemWatcher.StartRaisingEvents()
   at System.IO.FileSystemWatcher.StartRaisingEventsIfNotDisposed()
   at Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher.CreateFileChangeToken(String filter)
   at Microsoft.Extensions.Primitives.ChangeToken.OnChange(Func`1 changeTokenProducer, Action changeTokenConsumer)
   at Microsoft.Extensions.Configuration.Json.JsonConfigurationSource.Build(IConfigurationBuilder builder)
   at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
   at app.Shared.Utilities.GetAppConfig[T](String key, T defaultValue) in /var/app/source/app/app.Shared/Utilities.cs:line 33
   at System.IO.FileSystemWatcher.StartRaisingEvents()
   at System.IO.FileSystemWatcher.StartRaisingEventsIfNotDisposed()
   at Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher.CreateFileChangeToken(String filter)
   at Microsoft.Extensions.Primitives.ChangeToken.OnChange(Func`1 changeTokenProducer, Action changeTokenConsumer)
   at Microsoft.Extensions.Configuration.Json.JsonConfigurationSource.Build(IConfigurationBuilder builder)
   at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
   at app.Shared.Utilities.GetAppConfig[T](String key, T defaultValue) in /var/app/source/app/app.Shared/Utilities.cs:line 33

请告诉我这段代码有什么问题.

Tse*_*eng 11

var builder = new ConfigurationBuilder()
        .AddJsonFile($"appsettings.json", true, true);
Run Code Online (Sandbox Code Playgroud)

每次访问设置时,您都在创建文件监视器.第三个参数是reloadOnChange.

你必须确保,

var configuration = builder.Build()
Run Code Online (Sandbox Code Playgroud)

只在您的应用程序中调用一次并将其存储在您可以访问它的位置(最好是AVOID静态字段).

或者只是禁用文件观察器.

  var builder = new ConfigurationBuilder()
        .AddJsonFile($"appsettings.json", true, false);
Run Code Online (Sandbox Code Playgroud)

或清洁:

var builder = new ConfigurationBuilder()
        .AddJsonFile($"appsettings.json", optional: true, reloadOnChange: false);
Run Code Online (Sandbox Code Playgroud)

最好的方法是在接口后面抽象帽子并使用依赖注入.

public interface IConfigurationManager
{
    T GetAppConfig<T>(string key, T defaultValue = default(T));
}

public class ConfigurationManager : IConfigurationManager
{
    private readonly IConfigurationRoot config;

    public ConfigurationManager(IConfigurationRoot config)
        => this.config ?? throw new ArgumentNullException(nameof(config));

    public T GetAppConfig<T>(string key, T defaultValue = default(T))
    {
        T setting = (T)Convert.ChangeType(configuration[key], typeof(T));
        value = setting;
        if (setting == null)
            value = defaultValue;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后实例化并注册它

services.AddSingleton<IConfigurationManager>(new ConfigurationManager(this.Configuration));
Run Code Online (Sandbox Code Playgroud)

并通过构造函数将其注入您的服务


Dmi*_*lov 6

the configured user limit (128) on the number of inotify instances has been reached发生错误的原因是正确的 - 在非 Windows 环境中reloadOnChange访问appSetting.json文件时会导致问题。

但是在调整这个时你可能会错过一个想法。我除了设置reloadOnChangefalse

.AddJsonFile($"appsettings.json", optional: true, reloadOnChange: false);
Run Code Online (Sandbox Code Playgroud)

您还应该确保您没有从默认值开始,WebHost.CreateDefaultBuilder因为它内部 reloadOnChange也设置为true. 因此,控制您的网络主机的最佳方法是从头开始配置它,而不需要不需要的选项(例如,在您的环境WebHost.CreateDefaultBuilder.UseIISIntegration()也可能根本不需要)。

定制虚拟主机的例子-副本Microsoft WebHost.CreateDefaultBuilderIISFileWatcher依赖删除例如用于Linux环境。