NLog是否支持fail over机制?DB日志降级至文件日志需求咨询
NLog的Failover/Fallback功能支持及配置方法
当然可以!NLog完全支持你需要的故障转移/回退功能,刚好匹配你描述的场景——当数据库日志目标写入失败(比如DB宕机)时,自动切换到文件日志,而且不会同时往DB和文件写日志。
核心实现方式:使用<FallbackGroup>目标
NLog专门提供了FallbackGroup目标来处理这类场景——它会按顺序尝试组内的日志目标,直到找到一个能成功写入的目标;当主目标恢复正常后,还可以自动切回主目标(可选配置)。
XML配置示例
这是最常用的配置方式,直接在NLog.config中定义:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <!-- 主目标:数据库日志 --> <target name="dbTarget" xsi:type="Database" connectionString="YourDatabaseConnectionString" commandText="INSERT INTO Logs (LogLevel, Message, CreatedTime) VALUES (@level, @message, @timestamp)"> <!-- 数据库参数映射 --> <parameter name="@level" layout="${level}" /> <parameter name="@message" layout="${message}" /> <parameter name="@timestamp" layout="${date:format=yyyy-MM-dd HH\:mm\:ss}" /> </target> <!-- 备用目标:文件日志 --> <target name="fileTarget" xsi:type="File" fileName="${basedir}/logs/app-${shortdate}.log" layout="${longdate} [${level:uppercase=true}] ${message}" archiveEvery="Day" archiveNumbering="Rolling" maxArchiveFiles="30" /> <!-- 故障转移组:优先尝试dbTarget,失败则用fileTarget --> <target name="fallbackLogGroup" xsi:type="FallbackGroup" returnToFirstOnSuccess="true"> <target name="dbTarget" /> <target name="fileTarget" /> </target> </targets> <rules> <!-- 将所有日志路由到故障转移组 --> <logger name="*" minlevel="Info" writeTo="fallbackLogGroup" /> </rules> </nlog>
关键配置说明
returnToFirstOnSuccess="true":这个参数很实用,当数据库恢复正常后,NLog会自动切回主数据库目标,无需手动修改配置。如果设为false,一旦切换到备用目标,就会一直使用备用目标直到重启应用。- NLog会自动检测目标失败:当数据库目标抛出连接异常、写入异常等错误时,NLog会标记该目标为“失败”,并立即尝试下一个备用目标。后续会定期检查主目标的状态,恢复后自动切换回去。
代码配置示例(C#)
如果是在代码中动态配置NLog(比如ASP.NET Core项目),可以这样实现:
using NLog; using NLog.Config; using NLog.Targets; var config = new LoggingConfiguration(); // 配置数据库目标 var dbTarget = new DatabaseTarget("dbTarget") { ConnectionString = "YourDatabaseConnectionString", CommandText = "INSERT INTO Logs (LogLevel, Message, CreatedTime) VALUES (@level, @message, @timestamp)" }; dbTarget.Parameters.Add(new DatabaseParameterInfo("@level", "${level}")); dbTarget.Parameters.Add(new DatabaseParameterInfo("@message", "${message}")); dbTarget.Parameters.Add(new DatabaseParameterInfo("@timestamp", "${date:format=yyyy-MM-dd HH\\:mm\\:ss}")); config.AddTarget(dbTarget); // 配置文件目标 var fileTarget = new FileTarget("fileTarget") { FileName = "${basedir}/logs/app-${shortdate}.log", Layout = "${longdate} [${level:uppercase=true}] ${message}", ArchiveEvery = FileArchivePeriod.Day, MaxArchiveFiles = 30 }; config.AddTarget(fileTarget); // 配置故障转移组 var fallbackGroup = new FallbackGroupTarget("fallbackLogGroup") { ReturnToFirstOnSuccess = true, Targets = { dbTarget, fileTarget } }; config.AddTarget(fallbackGroup); // 添加日志规则 config.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, fallbackGroup)); // 应用配置 LogManager.Configuration = config; var logger = LogManager.GetCurrentClassLogger(); logger.Info("测试日志,优先写入DB,失败则写入文件");
总结
这个配置完全符合你的需求:
- 正常情况下,日志仅写入数据库目标
- 当数据库不可用时,自动切换到文件目标,不会同时写入两个目标
- 数据库恢复后,自动切回数据库目标(如果开启了
returnToFirstOnSuccess)
内容的提问来源于stack exchange,提问作者Ramya Gowda
相关产品推荐
相关产品推荐

