【个人博客搭建】(18)使用Quartz.NET 定时备份数据库

Quartz.NET在系统主要承担的一些关键功能:

  • 任务调度:Quartz.NET 允许开发人员创建、调度和管理定时任务,支持简单触发器和Cron表达式等多样化的触发策略。
  • 灵活性:Quartz.NET 提供了灵活的任务安排机制,不仅支持基于时间间隔的重复执行,还能根据特定日期、时间等信息来安排任务执行。
  • 高可用性:对于企业级应用,Quartz.NET 提供了路由支持、Group管理以及持久化机制,确保任务的高可用性和系统的稳定运行。
  • 集成性:Quartz.NET 可以与ASP.NET Core应用程序整合,通过Quartz.Extensions.Hosting包实现对后台任务的直接支持。

Quartz.NET 可以在博客系统中承担以下功能:

  1. 内容发布管理:可以设置定时任务来自动发布文章,例如在特定时间发布博文或定期发布一系列教程。
  2. 数据备份:可以安排定期执行数据库备份的任务,确保博客数据的安全。
  3. 定期维护:可以执行如清理垃圾文件、更新插件和系统等定期维护任务。
  4. 邮件通知:可以实现定时向订阅者发送邮件通知,比如最新文章的推送或者定期通讯。
  5. 访问统计分析:可以定时生成博客访问报告,分析访问量、用户行为等信息。
  6. 评论和回复处理:可以设置定时检查评论和回复的任务,对不良信息进行过滤或标记。
  7. 广告轮换:可以安排广告内容的自动更新和轮换。
  8. 社交媒体同步:可以安排任务将新内容自动分享到社交媒体平台。
  9. 反垃圾邮件措施:通过定时监控和清理,减少垃圾评论和留言。
  10. 用户体验优化:可以通过定期执行A/B测试或其他优化工作来改善用户体验。
  11. 搜索引擎优化(SEO):定期更新网站的SEO策略和关键字,以提高搜索引擎排名。
  12. 监控与告警:监控系统性能和可用性,并在出现问题时发送告警。

总的来说,Quartz.NET 的灵活性和强大功能使其成为博客系统中自动化管理任务的理想选择。通过继承 IJob 接口,你可以创建各种类型的作业来满足不同的需求。

这里,我们要处理的就是数据库备份的功能。

1、 安装 NuGet 包: Quartz.NET

2、创建一个作业类:创建一个继承自 IJob 接口的类,实现 Execute 方法,该方法将在指定的时间执行数据库备份操作。

(这里建议在解决方案下边新建一个类库Tasks)

using Quartz;
using System.Threading.Tasks;

public class BackupDatabaseJob : IJob
{
    public Task Execute(IJobExecutionContext context)
    {
        // 在这里执行数据库备份操作
        // ...
        return Task.CompletedTask;
    }
}

3、 配置。 在你的应用程序中,配置 Quartz.NET 以使用你的作业类和触发器。

using Quartz;
using Quartz.Impl;

public static async Task Main()
{
    // 创建调度器工厂
    StdSchedulerFactory factory = new StdSchedulerFactory();

    // 从工厂获取调度器实例
    IScheduler scheduler = await factory.GetScheduler();

    // 启动调度器
    await scheduler.Start();

    // 定义作业并将其与我们的作业类关联起来
    IJobDetail job = JobBuilder.Create<BackupDatabaseJob>().WithIdentity("backupJob").Build();

    // 定义触发器,设置作业执行的时间间隔
    ITrigger trigger = TriggerBuilder.Create()
        .WithIdentity("backupTrigger")
        .StartNow() // 立即开始
        .WithSimpleSchedule(x => x
            .WithIntervalInHours(24) // 每24小时执行一次
            .RepeatForever()) // 无限循环
        .Build();

    // 将作业和触发器添加到调度器中
    await scheduler.ScheduleJob(job, trigger);
}

 4、运行

5、待测试功能

        在执行任务那,我们需要引用其他方法,所以建议单独用一个类库项目存储

--------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------

【二】:续:

下边是项目中使用的简单案例:

1、创建一个帮助类


    public class QuartzHelper
    {
        private static IScheduler _scheduler;

        /// <summary>
        /// 初始化调度器
        /// </summary>
        /// <returns></returns>
        public static async Task InitializeAsync()
        {
            if (_scheduler == null)
            {
                var factory = new StdSchedulerFactory();
                _scheduler = await factory.GetScheduler();
                await _scheduler.Start();
            }
        }

        public static async Task<string> AddJobAsync<T>(string jobName, string groupName, TimeSpan interval) where T : IJob
        {
            if (_scheduler == null)
            {
                await InitializeAsync();
            }

            //var job = JobBuilder.Create<T>().WithIdentity(jobName, groupName).Build();
            //var trigger = TriggerBuilder.Create().WithIdentity($"{jobName}-trigger", groupName)
            //    .StartNow()
            //    .WithSimpleSchedule(x => x.WithInterval(interval).RepeatForever())
            //    .Build();

            //替换为:
            //反射执行程序集
            var jobClassName = typeof(T).Name;
            var baseType = typeof(IJob);
            var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
            var referencedAssemblies = System.IO.Directory.GetFiles(path, "plateau.poetize.blog.Tasks.dll").Select(Assembly.LoadFrom).ToArray();
            var jobType = referencedAssemblies
                .SelectMany(a => a.DefinedTypes)
                .Select(type => type.AsType())
                .Where(x => x.Name == jobClassName)
                .First();


            string times = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            //1、任务:
            IJobDetail job = new JobDetailImpl(times, groupName, jobType);//任务名称,任务组

            //2、触发器
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity(jobName + "-Trigger" + "-" + times, groupName)//触发器名称,任务组
                .StartNow() // 立即开始(后续有web界面时,不建议立即执行,每个操作都建议独立)
                .WithSimpleSchedule(x => x
                .WithIntervalInHours(12) // 每12小时执行一次
                .RepeatForever()) // 无限循环
                .Build();

            //3、参数(可无)
            job.JobDataMap.Add("JobParam", "参数:......");//共享的,也可以更改值
            job.JobDataMap.Add("JobRunNum", 1);//具体执行的时候可以更改值,打印

            //4、调度器
            var v = await _scheduler.ScheduleJob(job, trigger);
            Console.WriteLine("任务开始成功");
            return "任务开始成功";
        }

        public static async Task RemoveJobAsync(string jobName, string groupName)
        {
            if (_scheduler == null)
            {
                return;
            }

            await _scheduler.DeleteJob(new JobKey(jobName, groupName));
        }

        public static async Task StartAsync()
        {
            if (_scheduler == null)
            {
                await InitializeAsync();
            }

            await _scheduler.Start();
        }

        public static async Task StopAsync()
        {
            if (_scheduler == null)
            {
                return;
            }

            await _scheduler.Shutdown();
        }
    }

2、Job任务类:


    public class BackupDatabaseJob : IJob
    {

        /// <summary>
        /// 执行
        /// </summary>
        /// <param name="context">上下文</param>
        /// <returns></returns>
        public Task Execute(IJobExecutionContext context)
        {
            using (var serviceScope = MyApp.Instance.CreateScope())
            {
                var server = serviceScope.ServiceProvider.GetService<IMyJobService>();

                var list = server.BackupDatabase();

                //获取传递过来的参数
                JobDataMap data = context.JobDetail.JobDataMap;
                int jobRunNum = data.GetInt("JobRunNum");
                string jobParam = data.GetString("JobParam");
                ///
                Console.WriteLine($"BackupDatabaseJob 执行 {DateTime.Now.ToString()}");
                Console.WriteLine($"【JobRunNum】 :{jobRunNum}");
                Console.WriteLine($"【JobParam】: 执行 {jobParam}");

                修改值
                //jobRunNum++;
                //data["JobRunNum"] = jobRunNum; // 修改 JobDataMap 中的值
            }

            return Task.CompletedTask;
        }

    }

        上边与之前的差距主要就是在使用

        

//引入命名空间(nuget包)
using Microsoft.Extensions.DependencyInjection;


//代码
using (var serviceScope = MyApp.Instance.CreateScope()) 

        这里的MyApp是一个静态类

public static class MyApp
{

    public static IServiceProvider Instance { get; set; }

}

        这里值的赋值在入口文件中进行:

//写入静态类供全局获取
MyApp.Instance = app.Services;

3、注入服务:

//注入服务
builder.Services.AddTransient<IMyJobService, MyJobService>();
builder.Services.AddTransient<ISchedulerCenter, SchedulerCenterServer>();
//注入任务
builder.Services.AddTransient(typeof(BackupDatabaseJob));

        注入服务可以反射循环注入。 

4、运行:

await QuartzHelper.AddJobAsync<BackupDatabaseJob>("myJob_BackupDatabaseJob", "myGroup_BackupDatabaseJob", TimeSpan.FromHours(24));

5、效果:

6、拓展:

        6.1、目前使用的方式都是代码固定的,可创建模型进行参数化 

        6.2、后续还要做一个Web的可视化操作。

        6.3、因为异步,如果多层可能会得不到实际的返回值。

        6.4、共享参数的读取、赋值。记录日志等

        6.5、并发问题:(例如程序需要执行2秒,但是任务是1秒一次)。实际的执行时间大于给定任务时间。需要设置,然后会根据实际的任务时间进行循环。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/609311.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据挖掘(一)数据类型与统计

前言 打算新开一个笔记系列&#xff0c;基于国防科技大学 丁兆云老师的《数据挖掘》 数据挖掘 1、数据类型与统计 数据统计 最大值&#xff0c;最小值&#xff0c;平均值&#xff0c;中位数&#xff0c;位数&#xff0c;方差等统计指标 df.describe() #当调用df.describe(…

电池储能系统的电荷状态预测 | 利用数据驱动机器学习预测锂离子电池储能系统的电荷状态附代码

概述 准确估计电荷状态(SOC)对于保证锂离子电池储能系统的安全性和稳定性至关重要。然而,由于锂离子电池内多个复杂过程的耦合动力学,以及缺乏监测电池内部性能变化的措施,这项任务非常具有挑战性。近年来,随着图形处理器(GPU)计算能力的不断发展,深度学习作为 SOC 估计方…

# 从浅入深 学习 SpringCloud 微服务架构(十四)微服务链路追踪

从浅入深 学习 SpringCloud 微服务架构&#xff08;十四&#xff09;微服务链路追踪 一、微服务的链路追踪概述 1、微服务架构下的问题 在大型系统的微服务化构建中&#xff0c;一个系统会被拆分成许多模块。这些模块负责不同的功能&#xff0c;组合成系统&#xff0c;最终可…

java中的并发编程

1、上下文切换 即使是单核处理器也支持多线程执行代码&#xff0c;CPU通过给每个线程分配CPU时间片来实现 这个机制。这个时间片特别短&#xff0c;一般是几十毫秒&#xff0c;所以会让我们觉得好多任务同时进行。 CPU通过时间片分配算法来循环执行任务&#xff0c;当前任务执…

autolabor(ROS开发笔记)__1

视频链接&#xff1a;ROS机器人 chapter 1 ROS概述与环境搭建 学习步骤&#xff1a; 1.了解该模块的相关概念 是什么&#xff0c;为什么学&#xff0c;前世今生&#xff0c;发展前景 2.安装官方软件包 具备基本的开发环境&#xff0c;简陋notepad 3.搭建集成开发环境(IDE,Int…

打造抖音萌娃账户,一条广告轻松过万,副业兼职最佳选择(实例教程 素材内容)

我特别喜欢简单易操作的新项目&#xff0c;因为过于复杂和门槛高的项目对新手来说可能是毁灭性的&#xff0c;他们往往难以入门&#xff0c;而且付出努力也得不到反馈。 下 载 地 址 &#xff1a; laoa1.cn/1971.html 小宝宝小萌娃账户就相对简单&#xff0c;它类似于电视剧…

文字图形化:UI设计师的必备能力,带你看看为什么要这么做。

在UI设计中&#xff0c;文字尽可能要进行图形化设计的原因有以下几点&#xff1a; 提高识别性&#xff1a; 图形化设计可以通过视觉效果和形状来吸引用户的注意力&#xff0c;从而提高文字的可识别性。这有助于用户更快地理解并记住信息&#xff0c;同时也可以增强品牌的认知…

Python实现一个简单的计算器

简单版本 使用 Python 的 Tkinter 模块来实现一个简单的图形化计算器。以下是一个基本的示例代码 示例效果 代码源码 import tkinter as tkdef button_click(number):current entry.get()entry.delete(0, tk.END)entry.insert(0, current str(number))def button_clear():e…

翼支付——风控场景中图模型的范式变迁

目录 风控图深度学习模型 风控图大模型

ASP.NET校园新闻发布系统的设计与实现

摘 要 校园新闻发布系统是在学校区域内为学校教育提供资源共享、信息交流和协同工作的计算机网络信息系统。随着网络技术的发展和Internet应用的普及&#xff0c;互联网已成为人们获取信息的重要来源。由于现在各大学校的教师和学生对信息的需求越来越高&#xff0c;校园信息…

Redis未授权访问

一、漏洞描述 Redis未授权访问 因配置不当可以未经授权访问&#xff0c;攻击者无需认证就可以访问到内部数据。 1. 导致敏感信息泄露 2. 执行 flushall 可清空所有数据 3. 通过数据备份功能往磁盘写入后门文件&#xff08;webshell、定时任务&#xff09; 4. 如果Redis以…

Swift 集合类型

集合类型 一、集合的可变性二、数组&#xff08;Arrays&#xff09;1、数组的简单语法2、创建一个空数组3、创建一个带有默认值的数组4、通过两个数组相加创建一个数组5、用数组字面量构造数组6、访问和修改数组7、数组的遍历 三、集合&#xff08;Sets&#xff09;1、集合类型…

共识算法基础

目录 PaxosRaft节点间是如何通讯的什么是任期与任期编号选举有哪些规则随机超时时间Raft日志成员变更Nacos中Raft的运用&#xff08;cp模式&#xff09; DistroZAB协议博客 Paxos paxos算法是由兰伯特与1990年提出的一个分布式系统的共识算法。分布式系统的共识算法通俗易懂的…

【多客系统】社交圈子论坛系统,小程序/app/H5多端圈子社区论坛系统交友,社区圈子论坛小程序前后端搭建,社交圈平台系统

简述 社交圈子论坛系统是一种面向特定人群或特定话题的社交网络&#xff0c;它提供了用户之间交流、分享、讨论的平台。在这个系统中&#xff0c;用户可以创建、加入不同的圈子&#xff0c;圈子可以是基于兴趣、地域、职业等不同主题的。用户可以在圈子中发帖、评论、点赞等互…

聊聊 ASP.NET Core 中间件(二):中间件和筛选器的区别

前言 有些小伙伴看到上一篇文章后&#xff0c;可能会发现中间件和我们之前讲的筛选器非常类似&#xff0c;比如它们都是通过 next 串起来的一系列的组件&#xff0c;并且都可以在请求处理前后执行代码&#xff0c;都可以通过不执行 next 来进行请求的终止。那么筛选器和中间件…

风筝挂在高压线上怎么办?输电线路AI视频监测装置快速识别保平安

放风筝是一项既有趣又能够让人放松心情的活动&#xff0c;如今风筝的造型和设计也是越来越多样&#xff0c;各种形状奇特的风筝随风起舞&#xff0c;飘荡在空中。不过需要注意的是&#xff0c;由于风速变化无常&#xff0c;放风筝时稍不留神就会将风筝挂在高压线等公共基础设施…

从Apache HttpClient类库,说一说springboot应用程序中的AutoConfiguration的封装

一、背景 在使用httpclient框架请求http接口的时候&#xff0c;我们往往会需要自定义配置httpclient&#xff0c;而非直接使用。 <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>…

SPSS之主成分分析

SPSS中主成分分析功能在【分析】--【降维】--【因子分析】中完成&#xff08;在SPSS软件中&#xff0c;主成分分析与因子分析均在【因子分析】模块中完成&#xff09;。 求解主成分通常从分析原始变量的协方差矩阵或相关矩阵着手。 &#xff08;1&#xff09;当变量取值的度量…

20232820 2023-2024-2 《网络攻防实践》实践九报告

20232820 2023-2024-2 《网络攻防实践》实践九报告 1.实践内容 本次实践的对象是一个名为pwn1的linux可执行文件。 该程序正常执行流程是&#xff1a;main调用foo函数,foo函数会简单回显任何用户输入的字符串。 该程序同时包含另一个代码片段&#xff0c;getShell&#xff…

从开发角度理解漏洞成因(02)

文章目录 文件上传类需求文件上传漏洞 文件下载类需求文件下载漏洞 扩展 留言板类&#xff08;XSS漏洞&#xff09;需求XSS漏洞 登录类需求cookie伪造漏洞万能密码登录 持续更新中… 文章中代码资源已上传资源&#xff0c;如需要打包好的请点击PHP开发漏洞环境&#xff08;SQL注…