web-dev-qa-db-ja.com

dotnetコアのjsonファイルの読み取り中にエラーが発生しました「inotifyインスタンス数の設定済みユーザー制限(128)に達しました」

コンソールアプリケーション(ドットネットコア1.1)があり、cronスケジューラで1分ごとにスケジュールされています。アプリケーション内には、構成ファイルへの呼び出しがあります。以下のコードを添付します。

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

しばらくアプリケーションを実行した後、このエラーは「inotifyインスタンス数の設定済みユーザー制限(128)に達した」というログファイルに記録されます。完全なスタックトレースを見つけてください。

適用されたアプリキーDeviceIdのデフォルト値の読み取り中に例外が発生しました。
 System.IO.IOException:inotifyインスタンス数の構成済みユーザー制限(128)に達しました。
 at System.IO.FileSystemWatcher.StartRaisingEvents()
 at System.IO.FileSystemWatcher.StartRaisingEventsIfNotDisposed()
 at Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher.CreateFileChangeToken(String filter)
 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 
 System.IO.FileSystemWatcher.StartRaisingEvents()
 at System.IO.FileSystemWatcher.StartR a.EventsIfNotDisposed()
 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)/ /var/app/source/app/app.Shared/Utilities.cs:line 33 

このコードのどこが悪いのか教えてください。

11
Vipin
var builder = new ConfigurationBuilder()
        .AddJsonFile($"appsettings.json", true, true);

設定にアクセスするたびに、ファイルウォッチャーを作成しています。 3番目のパラメーターはreloadOnChangeです。

確認する必要があります

var configuration = builder.Build()

アプリケーションで1回だけ呼び出され、アクセスできる場所に保存します(できれば[〜#〜] avoid [〜#〜]静的フィールド)。

または、ファイルウォッチャーを無効にします。

  var builder = new ConfigurationBuilder()
        .AddJsonFile($"appsettings.json", true, false);

またはクリーナー:

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

最善の方法は、インターフェースの背後でそれを抽象化し、依存性注入を使用することです。

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

次にインスタンス化して登録します

services.AddSingleton<IConfigurationManager>(new ConfigurationManager(this.Configuration));

コンストラクタを介してサービスに注入します

13
Tseng

エラー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);
_

内部reloadOnChangetrueに設定されているため、デフォルトの_WebHost.CreateDefaultBuilder_から始めないようにしてください。したがって、Webホストが何であるかを制御する最良の方法は、不要なオプションなしでゼロから構成することです(たとえば、_WebHost.CreateDefaultBuilder_も.UseIISIntegration()を実行しますが、環境ではまったく必要ありません)。 。

カスタムWebホストの例 -Microsoft _WebHost.CreateDefaultBuilder_のコピーですが、IISおよびFileWatcherの依存関係が削除されています。 Linux環境用。

3
Dmitry Pavlov

ファイルが変更されると、設定が自動的にリロードされるようです。そのため、アプリケーションの起動時に一度だけ構成を作成し、それから読み取るだけで済みます。

1
Dan