Quartz任务调度 服务日志+log4net打印日志+制作windows服务
引言
现在许多的项目都需要定时的服务进行支撑,而我们经常用到的定时服务就是Quartz任务调度了。不过我们在使用定时Job进行获取的时候,有时候我们就需要记录一下自定义的日志,甚至我们还会对执行定时Job脚本中,本身的线程启动和触发器等相关信息进行记录,这就用到了Common.Logging.log4net了,但同时它在控制台上输出相应信息的同时,并不能对这些信息进行日志文件的记录与存储。
有关log4net的相关使用,详情请看之前的博文:http://www.cnblogs.com/huanghzm/p/4754890.html
而本文的主要目的就是处理Quartz系统日志与log4net的相互结合,最后附带说明了利用Topshlef坐直windows服务。
准备
1、安装指定的程序包
Install-Package Quartz
Install-Package Common.Logging.Log4Net1211(安装这个的时候会自定安装其依赖项,即Log4Net)
Install-Package Topshelf
2、配置文件设置
<configSections> <sectionGroup name="common"> <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" /> </sectionGroup> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> </configSections> <common> <logging> <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net1211"> <arg key="configType" value="INLINE" /> </factoryAdapter> </logging> </common> <log4net> <!--错误日志--> <!--自定义错误异常--> <appender name="CustomExAppender" type="log4net.Appender.RollingFileAppender"> <param name="File" value="Log\\LogCustomEx\\" /> <param name="AppendToFile" value="true" /> <param name="MaxFileSize" value="10240" /> <param name="MaxSizeRollBackups" value="100" /> <param name="StaticLogFileName" value="false" /> <param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" /> <param name="RollingStyle" value="Date" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n日志描述:%message%newline %n" /> </layout> </appender> <appender name="ErrorExAppender" type="log4net.Appender.RollingFileAppender"> <param name="File" value="Log\\LogErrorEx\\" /> <param name="AppendToFile" value="true" /> <param name="MaxFileSize" value="10240" /> <param name="MaxSizeRollBackups" value="100" /> <param name="StaticLogFileName" value="false" /> <param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" /> <param name="RollingStyle" value="Date" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n日志描述:%message%newline %n" /> </layout> </appender> <!--CustomEx日志--> <logger name="LogCustomEx"> <level value="INFO" /> <appender-ref ref="CustomExAppender" /> </logger> <!--Error日志--> <logger name="LogErrorEx"> <level value="ERROR" /> <appender-ref ref="ErrorExAppender" /> </logger> <!--服务执行日志--> <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender"> <param name="File" value="Log\\ServerLog\\" /> <param name="AppendToFile" value="true" /> <param name="MaxFileSize" value="10240" /> <param name="MaxSizeRollBackups" value="100" /> <param name="StaticLogFileName" value="false" /> <param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" /> <param name="RollingStyle" value="Date" /> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%n%date{HH:mm:ss,fff} [%-5level] %m" /> </layout> </appender> <!-- 控制台前台显示日志 --> <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> <mapping> <level value="ERROR" /> <foreColor value="Red, HighIntensity" /> </mapping> <mapping> <level value="Info" /> <foreColor value="Green" /> </mapping> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%n%date{HH:mm:ss,fff} [%-5level] %m" /> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="Info" /> <param name="LevelMax" value="Fatal" /> </filter> </appender> <root> <!--(高) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (低) --> <level value="all" /> <appender-ref ref="ColoredConsoleAppender"/> <appender-ref ref="RollingLogFileAppender"/> </root> </log4net>
让世界跑起来
1、配置相关Job类(JobInfo[对象]、JobType[类型]、JobInfoList[触发器、时间]) 名称、触发器、群组、类型(根据不同的类型执行不同的Job内容)
public class JobInfo { public JobInfo(string jobName, string group, string trigger, JobType jobType) { if (jobName == null || trigger == null || group == null) { throw new ArgumentNullException("jobName"); } this.JobName = jobName; this.Trigger = trigger; this.Group = group; this.JobType = jobType; } /// <summary> /// 名称 /// </summary> public string JobName { get; set; } /// <summary> /// Job的触发器 cron表达式 /// </summary> public string Trigger { get; set; } /// <summary> /// 群组 /// </summary> public string Group { get; set; } /// <summary> /// Job类型 /// </summary> public JobType JobType { get; set; } } /// <summary> /// Job类型枚举 /// </summary> public enum JobType { /// <summary> /// 任务1 /// </summary> Job1 = 1, /// <summary> /// 任务2 /// </summary> Job2 = 2 }
public class JobInfoList { /// <summary> /// 脚本服务组 /// </summary> public static List<JobInfo> JobList_ZhongShanHos = new List<JobInfo> { new JobInfo("任务1", "测试脚本", "*/5 * * * * ?", JobType.Job1), new JobInfo("任务2", "测试脚本", "*/7 * * * * ?", JobType.Job2) }; }
2、配置具体的Job内容与需要输出的自定义日志,这里的日志使用log4net作为记录 (TestJob.cs)
public class TestJob : IJob { private static readonly log4net.ILog LogInfo = log4net.LogManager.GetLogger("LogCustomEx"); private static readonly log4net.ILog LogError = log4net.LogManager.GetLogger("LogError"); public void Execute(IJobExecutionContext context) { var map = context.JobDetail.JobDataMap; var jobInfo = map["KEY"] as JobInfo; if (jobInfo == null) { return; } //记录日志 LogInfo.Info("\n【服务已启动】" + "\n【启动组】:" + jobInfo.Group + "\n【启动名称】:" + jobInfo.JobName + "\n【启动时间】:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); try { switch (jobInfo.JobType) { //基础信息 case JobType.Job1: LogInfo.Info("这是任务1"); break; case JobType.Job2: LogInfo.Info("这是任务2"); break; default: break; } } catch (Exception ex) { //记录日志 LogError.Error("\n【服务执行出错】" + "\n【启动组】:" + jobInfo.Group + "\n【启动名称】:" + jobInfo.JobName + "\n【时间】:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\n【错误信息】:" + ex.Message); return; } } }
3、配置Job执行方法
public sealed class ServerRunner : ServiceControl, ServiceSuspend { private readonly IScheduler scheduler; public ServerRunner() { scheduler = StdSchedulerFactory.GetDefaultScheduler(); } public bool Start(HostControl hostControl) { var jobList = new List<JobInfo>(); //配置JobList任务 jobList.AddRange(JobInfoList.JobList_ZhongShanHos); jobList.ForEach( x => { var dic = new Dictionary<string, JobInfo> { { "KEY", x } }; var map = new JobDataMap(dic); var job = JobBuilder.Create<TestJob>() .WithIdentity(x.JobName, x.Group) .UsingJobData(map) .RequestRecovery() .Build(); var trigger = TriggerBuilder.Create() .WithIdentity(x.JobName, x.Group) .WithCronSchedule(x.Trigger) .Build(); scheduler.ScheduleJob(job, trigger); }); scheduler.Start(); return true; } public bool Stop(HostControl hostControl) { scheduler.Shutdown(false); return true; } public bool Continue(HostControl hostControl) { scheduler.ResumeAll(); return true; } public bool Pause(HostControl hostControl) { scheduler.PauseAll(); return true; } }
4、配置入口文件
class Program { static void Main(string[] args) { //配置Log4日志 log4net.Config.XmlConfigurator.Configure(); //Windows服务 HostFactory.Run(x => { x.UseLog4Net(); x.Service<ServerRunner>(); x.SetDescription("Quartz日志记录服务"); x.SetDisplayName("Quartz"); x.SetServiceName("QuartzLog"); x.EnablePauseAndContinue(); }); } }
至此,基本的所有配置就这样完成了,只要运行,就可以看到对应的服务的信息了。
日志信息也记录在对应的(前面说设计的文档中)按照相面的代码选定的地址是根目录文件,如图所示:
windows服务
制作windows服务,非常简单,只要调出cmd命令行,cd到指定文件的目录,输入应用程序名+install就可以,卸载的话就输入uninstall就可以了。如图所示:
源代码地址:GitHub
链接:https://github.com/JaminHuang/QuartzLog.git