在 dotnet 核心 "the configured user limit (128) on the number of inotify instances has been reached" 中读取 json 文件时出错
Error while reading json file in dotnet core "the configured user limit (128) on the number of inotify instances has been reached"
我有一个控制台应用程序(在 dot net core 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;
}
应用程序 运行 一段时间后,此错误出现在我的日志文件 "the configured user limit (128) on the number of inotify instances has been reached" 中。请找到完整的堆栈跟踪。
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
请告诉我这段代码有什么问题。
看起来配置会在文件更改时自动重新加载。因此,您应该只在应用程序启动时构建一次配置,然后从中读取。
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", true, true);
您每次访问设置时都在创建文件观察器。第三个参数是reloadOnChange
。
你必须确定,
var configuration = builder.Build()
在您的应用程序中只调用一次并将其存储在您可以访问它的地方(最好是避免它的静态字段)。
或者只禁用文件观察器。
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));
并通过构造函数将其注入到您的服务中
错误 the configured user limit (128) on the number of inotify instances has been reached
发生的原因是正确的 - 在非 Windows 环境中 reloadOnChange
导致访问 appSetting.json
文件时出现问题。
但是有一个想法你在调整这个的时候可能会错过。我除了将 reloadOnChange
设置为 false
之外:
.AddJsonFile($"appsettings.json", optional: true, reloadOnChange: false);
您还应该确保您没有从默认 WebHost.CreateDefaultBuilder
开始,因为 inside it reloadOnChange
也设置为 true
。因此,控制您的虚拟主机的最佳方式是从头开始配置它,而不需要不需要的选项(例如 WebHost.CreateDefaultBuilder
也执行 .UseIISIntegration()
,这在您的环境中可能根本不需要)。
example of custom web host - Microsoft
WebHost.CreateDefaultBuilder
的副本,但删除了 IIS
和 FileWatcher
依赖项,例如Linux
环境。
我有一个控制台应用程序(在 dot net core 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;
}
应用程序 运行 一段时间后,此错误出现在我的日志文件 "the configured user limit (128) on the number of inotify instances has been reached" 中。请找到完整的堆栈跟踪。
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
请告诉我这段代码有什么问题。
看起来配置会在文件更改时自动重新加载。因此,您应该只在应用程序启动时构建一次配置,然后从中读取。
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", true, true);
您每次访问设置时都在创建文件观察器。第三个参数是reloadOnChange
。
你必须确定,
var configuration = builder.Build()
在您的应用程序中只调用一次并将其存储在您可以访问它的地方(最好是避免它的静态字段)。
或者只禁用文件观察器。
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));
并通过构造函数将其注入到您的服务中
错误 the configured user limit (128) on the number of inotify instances has been reached
发生的原因是正确的 - 在非 Windows 环境中 reloadOnChange
导致访问 appSetting.json
文件时出现问题。
但是有一个想法你在调整这个的时候可能会错过。我除了将 reloadOnChange
设置为 false
之外:
.AddJsonFile($"appsettings.json", optional: true, reloadOnChange: false);
您还应该确保您没有从默认 WebHost.CreateDefaultBuilder
开始,因为 inside it reloadOnChange
也设置为 true
。因此,控制您的虚拟主机的最佳方式是从头开始配置它,而不需要不需要的选项(例如 WebHost.CreateDefaultBuilder
也执行 .UseIISIntegration()
,这在您的环境中可能根本不需要)。
example of custom web host - Microsoft
WebHost.CreateDefaultBuilder
的副本,但删除了 IIS
和 FileWatcher
依赖项,例如Linux
环境。