如何禁用默认的 asp net core config change watcher?

Posted

技术标签:

【中文标题】如何禁用默认的 asp net core config change watcher?【英文标题】:How can I disable the defaul aspnet core config change watcher? 【发布时间】:2019-10-15 01:46:03 【问题描述】:

我有一个在 Docker 容器中运行的 ASPNET 核心应用程序。我目前无法启动超过 64 个容器 (initially described here) 我创建的图像。

通过交互式运行容器,我在启动阶段发现了这个错误。

未处理的异常:System.IO.IOException:已达到配置的 inotify 实例数量的用户限制 (128)。

在 System.IO.FileSystemWatcher.StartRaisingEvents() 在 System.IO.FileSystemWatcher.StartRaisingEventsIfNotDisposed() 在 System.IO.FileSystemWatcher.set_EnableRaisingEvents(布尔值) 在 Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher.TryEnableFileSystemWatcher() 在 Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher.CreateFileChangeToken(字符串过滤器) 在 Microsoft.Extensions.FileProviders.PhysicalFileProvider.Watch(字符串过滤器) 在 Microsoft.Extensions.Configuration.FileConfigurationProvider.<.ctor>b__0_0()

在 Microsoft.Extensions.Primitives.ChangeToken.OnChange(Func`1 changeTokenProducer, Action changeTokenConsumer) 在 Microsoft.Extensions.Configuration.FileConfigurationProvider..ctor(FileConfigurationSource 源) 在 Microsoft.Extensions.Configuration.Json.JsonConfigurationSource.Build(IConfigurationBuilder 生成器) 在 Microsoft.Extensions.Configuration.ConfigurationBuilder.Build() 在

Microsoft.AspNetCore.Hosting.WebHostBuilder.BuildCommonServices(AggregateException& hostingStartupErrors) 在 Microsoft.AspNetCore.Hosting.WebHostBuilder.Build() 在 /src/MyProjectName/Program.cs:line 10 中的 MyProjectName.Program.Main(String[] args) 处

Program.cs只有默认内容

 1 using Microsoft.AspNetCore;
 2 using Microsoft.AspNetCore.Hosting;
 3
 4 namespace CmcIiiCgiSim
 5 
 6    public class Program
 7    
 8        public static void Main(string[] args)
 9        
10            CreateWebHostBuilder(args).Build().Run();
11        
12
13        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
14            WebHost.CreateDefaultBuilder(args)
15                .UseStartup<Startup>();
16     
17 

监视配置更改似乎是 ASP 或任何 ASPNET 核心应用程序的默认设置 (see MS documentation)

我的问题是:如何在 settings 中为 existing 配置文件禁用此选项? 希望这也会禁用文件系统观察程序并消除错误。

我发现了很多示例,这些示例说明了如何以编程方式为其他设置文件完成。但在我的情况下,配置不会改变,我宁愿拥有一个不限于 64 个容器的图像。

【问题讨论】:

默认观察的唯一配置是 JSON(appsettings.jsonappsettings.environment.json)。包含该配置的方法有一个参数来启用或不启用重新加载。 我从这条评论中了解到,在配置中确实有 no 方法可以做到这一点。对吗? 你从哪里得到的?将 reload 设置为 false,这会禁用 watcher。 怎么样?我在这里完全傻了? 【参考方案1】:

默认构建器非常固执己见,并在已设置重新加载的情况下加载 appsettings。无法替换默认构建器中设置的配置。从 .NET Core 3.1.7 开始,这是 CreateDefaultBuilder 方法,其标志已更改以停止重新加载。我已经使用此配置运行了一个服务器,并确认没有创建 FileSystemWatchers。

    public static IHostBuilder CreateDefaultBuilder(string[] args)
        
            HostBuilder hostBuilder = new HostBuilder();
            hostBuilder.UseContentRoot(Directory.GetCurrentDirectory());
            hostBuilder.ConfigureHostConfiguration((Action<IConfigurationBuilder>) (config =>
            
                config.AddEnvironmentVariables("DOTNET_");
                config.AddCommandLine(args);
            ));
            hostBuilder.ConfigureAppConfiguration((hostingContext, config) =>
                
                    IHostEnvironment hostingEnvironment = hostingContext.HostingEnvironment;
                    config.AddJsonFile("appsettings.json", true, false)
                        .AddJsonFile("appsettings." + hostingEnvironment.EnvironmentName + ".json", true, false);
                    if (hostingEnvironment.IsDevelopment() &&
                        !string.IsNullOrEmpty(hostingEnvironment.ApplicationName))
                    
                        Assembly assembly = Assembly.Load(new AssemblyName(hostingEnvironment.ApplicationName));
                        if (assembly != null)
                            config.AddUserSecrets(assembly, true);
                    

                    config.AddEnvironmentVariables();
                    config.AddCommandLine(args);
                )
                .ConfigureLogging((hostingContext, logging) =>
                
                    int num = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? 1 : 0;
                    if (num != 0)
                        logging.AddFilter<EventLogLoggerProvider>(level => level >= LogLevel.Warning);
                    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                    logging.AddConsole();
                    logging.AddDebug();
                    logging.AddEventSourceLogger();
                    if (num == 0)
                        return;
                    logging.AddEventLog();
                )
                .UseDefaultServiceProvider((Action<HostBuilderContext, ServiceProviderOptions>) ((context, options) =>
                
                    bool flag = context.HostingEnvironment.IsDevelopment();
                    options.ValidateScopes = flag;
                    options.ValidateOnBuild = flag;
                ));
            return hostBuilder;
        

其中的关键部分是对AddJsonFile 的调用。第三个参数作为false 传递,禁用文件系统观察器。

【讨论】:

【参考方案2】:

我已经设法使用带有以下 sn-p 的默认构建器禁用监视 json 文件(在 linux 上):


IWebHostBuilder builder = WebHost.CreateDefaultBuilder();

builder.ConfigureAppConfiguration((context, config) =>

    foreach (var s in config.Sources)
    
        if (s is FileConfigurationSource)
            ((FileConfigurationSource)s).ReloadOnChange = false;
    
);

现在系统不再用尽 inotify 句柄了。

【讨论】:

这会通知应用程序有关配置所在的根文件夹中的任何更改。但由于某种原因,它还会通知所有子目录中的任何更改。我发现 Filewatcher 有一些字符串分配,但不知道为什么,因为我没有在任何地方使用它。事实证明,它触发非常频繁,因为它是由 root/Logs/... 中的更改触发的,并且创建的 FileSystemWatcher 具有 IncludeSubdirectories = true;默认情况下,每次记录某些内容时,它都会将更改的日志文件的路径与配置文件进行比较。无论如何,这个解决方案解决了它。

以上是关于如何禁用默认的 asp net core config change watcher?的主要内容,如果未能解决你的问题,请参考以下文章