在 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、服务管理器等)重启应用。
- 在生产环境中,自动重启的机制要加防抖、加校验,避免因频繁改动导致不停重启。
- 运维策略上,可以结合容器 / 服务管理器脚本监控配置文件变更,实现平滑重启。