在 ASP.NET Core 中,修改 appsettings 后如何优雅重启或刷新配置

在 ASP.NET Core 项目中,很多配置都写在 appsettings.json 或 appsettings.{环境}.json 中。正常情况下,程序启动时加载这些配置后就一直保持不变。若你在运行时修改了这些配置,如何让程序“看到”新配置或重启以使新配置生效,是一个很常见的问题。

下面我们逐步分析几种方案与注意事项,并给出示例代码与场景建议。

reloadOnChange + 配置监控(推荐用于多数场景)

.NET 的配置系统支持文件级别的监控(基于 FileSystemWatcher),通过 reloadOnChange 参数可以让配置在文件变更时被重新加载。

在 Program.cs 或启动配置处,通常写为:

builder.Configuration
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
    .AddEnvironmentVariables();

当某个 JSON 文件被修改时,系统会触发变更通知机制。

但是,仅有 reloadOnChange 并不足以让所有地方的配置自动更新。这时就需要用到 IOptionsMonitor<T> 或者其他变种。

使用 IOptionsMonitor

IOptionsMonitor<T> 是一个支持监控变化的选项接口。你可以注入它,并在变化时执行回调。示例:

public class MyService
{
    private MySettings _current;
    public MyService(IOptionsMonitor<MySettings> monitor)
    {
        _current = monitor.CurrentValue;
        monitor.OnChange(updated =>
        {
            _current = updated;
            // 这里可以根据新配置做一些调整,比如刷新缓存、重新连接等
        });
    }

    public void DoSomething()
    {
        // 使用 _current 中的最新值
    }
}

这样,当配置文件被修改、监控系统检测到变更后,就可以在运行时更新对应的值,不需要整个应用重启。

不过要注意:如果你把配置注入给单例服务(Singleton)作为在构造函数中读取一次的方式,那这个服务不会在后续自动拿到更新的配置。因此要避免这种“在构造函数里固定读取一次”的写法;或者把这些服务也改为能响应变化的结构。

此外,对于请求级别的服务,可以用 IOptionsSnapshot<T>,它在每个 HTTP 请求中都会从当前配置快照读取。适合 Web API / MVC 场景。

优势与局限

优势:无需重启应用即可使部分配置变更生效,减少中断。

局限:并非所有配置都适合动态变更(例如中间件注册、服务启动时的连接字符串、缓存种子等)。这些往往只能在应用启动阶段才能确定。

如果你修改的配置是影响启动流程的(例如管道注册、依赖注入结构、静态初始化逻辑等),单纯的 reloadOnChange + IOptionsMonitor 无法处理,那就需要重启应用或采用下述的方法。

在运行时主动触发应用重启

如果你修改的配置确实需要应用完全重新启动,有几种方式可以考虑。

方法 1:在 ASP.NET Core 中监听配置变更然后调用 StopApplication

你可以在配置阶段注册变更令牌(Change Token),一旦检测到配置变更,调用 IHostApplicationLifetime.StopApplication() 来停止当前应用。应用被停止后,在托管环境(如 IIS、Kestrel + systemd 等)会重启。示例如下:

public void Configure(IApplicationBuilder app, IConfiguration config, IHostApplicationLifetime lifetime)
{
    ChangeToken.OnChange(() => config.GetReloadToken(), () =>
    {
        // 配置变更时触发停止程序
        lifetime.StopApplication();
    });

    // 其他中间件注册 ...
}

在某些回答中,这被用来实现在 JSON 配置变更时自动重启整个 Web 应用。

这种方法有个风险:改变配置文件可能会触发多次变更通知,你要避免重复重启(可以做一个防抖机制或延迟判断)。

方法 2:修改与 ASP.NET Core 托管环境相关的文件以触发重启

在传统的 ASP.NET 应用中,修改 web.config 会使应用池重启;在 ASP.NET Core 部署在 IIS 上时,即便 web.config 主要用于 IIS 控制,也可以利用“触发变动”的原理来重启 ASP.NET Core 应用。有人通过对 web.config 做微小改动来让 IIS 重新加载应用。 

不过这种方式比较 hack,也依赖于你的部署环境(是否在 IIS 下、是否允许修改 web.config 等)。

方法 3:手动/脚本重启宿主环境

你也可以通过脚本、运维工具来监测配置文件变动,然后重启宿主进程或容器。例如:

  • 在 Linux 下监控配置文件改动,执行 systemctl restart your-app.service
  • 在容器环境中重启容器
  • 在 Windows 上重启 App Pool 或 IIS 应用

这种方式虽然笨重,但在很多部署环境中是比较稳定可控的方案。

总结与实践建议

  • 对于大部分可动态修改的业务配置,推荐使用 reloadOnChange: true + IOptionsMonitor<T> 或 IOptionsSnapshot<T> 方案,这样无需重启即可响应配置变更。
  • 对于影响启动流程的配置变动(如中间件注册、服务注入结构等),则需要重启应用。可以使用 ChangeToken + StopApplication,或让部署环境(IIS、服务管理器等)重启应用。
  • 在生产环境中,自动重启的机制要加防抖、加校验,避免因频繁改动导致不停重启。
  • 运维策略上,可以结合容器 / 服务管理器脚本监控配置文件变更,实现平滑重启。
评论