我有一个控制台应用程序(在网络核心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;
}
在运行应用程序一段时间之后,此错误进入我的日志文件&#34;已达到inotify实例数量的已配置用户限制(128)&#34;。请找到完整的堆栈跟踪。
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
请告诉我这段代码有什么问题。
答案 0 :(得分:10)
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", true, true);
每次访问设置时,您都在创建文件监视器。第三个参数是reloadOnChange
。
你必须确保,
var configuration = builder.Build()
只在您的应用程序中调用一次,并将其存储在您可以访问它的位置(最好是 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));
并通过构造函数
将其注入您的服务答案 1 :(得分:1)
错误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
环境。
答案 2 :(得分:0)
看起来配置会在文件更改时自动重新加载。因此,您应该只在应用程序启动时构建一次配置,然后从中读取。