关于 liunx 下 IOptionsMonitor 不能即时变化
今天遇到个奇怪问题,在.net 8中 IOptionsMonitor 选项,修改配置文件后不立即生效,重启服务器后又生效;增加 IOptionsMonitor OnChange 监听事件后发现在 Windows 情况下能正常监听,在Liunx 下就无法监听;
结解办法和思路:
在 .NET 8 里 IOptionsMonitor<T> 只有在配置源触发“变更通知”时才会更新(触发 OnChange,并让下一次 CurrentValue 取到新值)。你在 Linux 下改了配置文件但“未生效”,而重启后又生效,通常说明:应用启动时读到了新文件,但运行时没有收到文件变更事件或变更没有被正确绑定/读取。
检查没有开启 reloadOnChange: true,通常情况下系统默认加载的 appsettings.json 会自动开启;
如果你自己用 ConfigurationBuilder,需要显式开启:
builder.Configuration
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true);
查看Liunx 下 inotify 监听数:
cat /proc/sys/fs/inotify/max_user_instances (我这默认 128) cat /proc/sys/fs/inotify/max_user_watches (我这默认 60696) cat /proc/sys/fs/inotify/max_queued_events (我这默认 16384)
临时调大 监听数:
sudo sysctl -w fs.inotify.max_user_instances=1024 (我只调了这个,重启服务后 Onchange 事件就可以监听到了) sudo sysctl -w fs.inotify.max_user_watches=524288 sudo sysctl -w fs.inotify.max_queued_events=32768
永久修改(我这默认就修改一个):
修改
sudo tee /etc/sysctl.d/99-dotnet-inotify.conf >/dev/null <<'EOF' fs.inotify.max_user_instances=1024 EOF
加载:
sudo sysctl --system
检查:
sysctl fs.inotify.max_user_instances
sysctl fs.inotify.max_user_watches
sysctl fs.inotify.max_queued_events
查看那些进程监听的数量多:
sudo bash -c '
for pid in /proc/[0-9]*; do
p=${pid#/proc/}
c=$(ls -l /proc/$p/fd 2>/dev/null | grep -c inotify)
if [ "$c" -gt 0 ]; then
cmd=$(tr "\0" " " < /proc/$p/cmdline 2>/dev/null)
echo "$c $p $cmd"
fi
done | sort -nr | head -30
'
总结:
Linux 上你的进程没能再创建/使用 inotify 实例(fs.inotify.max_user_instances 太小或已被其它进程占满),导致 FileSystemWatcher 失效,从而 IOptionsMonitor.OnChange 不触发;重启后之所以“配置生效”,是因为启动时重新读取了文件,但运行时没法监听变更。

浙公网安备 33010602011771号