首页 > 编程语言 >ASP.NET Core 用 Hangfire 实现定时任务周期任务

ASP.NET Core 用 Hangfire 实现定时任务周期任务

时间:2023-05-22 09:22:06浏览次数:51  
标签:Core ASP 数据库 Hangfire var new NET

前言

系统经常会有一些逻辑或任务,需要定时执行或周期性执行,为了实现这个需求,一般有以下几种方式选择:

  • 后台任务,即 IHostedService
  • 开源库:Hangfire
  • 开源库:Quartz.net

这里,说下Hangfire的使用。

官网

https://www.hangfire.io/

Hangfire – Background jobs and workers for .NET and .NET Core 。

An easy way to perform background processing in .NET and .NET Core applications. No Windows Service or separate process required.

Backed by persistent storage. Open and free for commercial use.

是什么、为什么

它就是一个开源库,用于在程序中,定时做些什么,或周期性的做些什么。

使用它,让在.net应用中,编写任务调度类似的功能,更方便快速。比如在ASP.NET Core中,不再需要自己基于 IHostedService和计时器等,完整的写完一套定时或周期性任务。

以下是它可以做的事:

image-20230522083620030

其它

首先,它适用于任何.NET平台(.NET Framework 4.5 or later, .NET Core 1.0 or later, or any platform compatible with .NET Standard 1.3),与特定的.NET应用程序类型无关。

Hangfire通常在IIS进程中运行(尽管它也可以在控制台应用程序中运行)。 Hangfire的主要优点是开发人员无需登录IIS服务器即可创建计划任务。

一些特征和优点:

i0

重要概念:

Storage:一个后台任务相关信息的存储工具,一个任务的类型,方法,参数等都经序列化后放在Storage里。这个Storage可以是关系型数据库或非关系型数据库。

在ASP.NET Core中的使用(用SQL Server作为Storage)

安装NuGet包:

dotnet add package Hangfire.Core
dotnet add package Hangfire.SqlServer
dotnet add package Hangfire.AspNetCore

创建一个新的数据库当做Storage,或使用一个原有的数据库,

这里的后端指的是任务队列的存储后端,也就是 Hangfire 文档中写的 Storage。看了一下官网,大部分关系型非关系型数据库都是可以的。

这里先使用SQL Server。

Corn 表达式

在使用HangFire前,得先了解Corn表达式的使用:

如何在ASP.NET Core MVC 中使用

安装Nuget

dotnet add package Hangfire.Core
dotnet add package Hangfire.SqlServer
dotnet add package Hangfire.AspNetCore

这里先使用SQL Server,作为相关任务信息的数据存储。

先定义两个扩展方法,用于相关服务注册、和作为中间件使用

这样可以让程序的 startup.cs 或 program.cs 更加简洁清晰,提高可读性和减少更改。

比如在 HangfireExtension 类中定义:

    public static class HangfireExtension
    {
        public static void AddMyHangfire(this IServiceCollection services, IConfiguration configuration)
        {
            services.AddHangfire(configuration => configuration
                    .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
                    .UseSimpleAssemblyNameTypeSerializer()
                    .UseRecommendedSerializerSettings()
                    .UseSqlServerStorage("Hangfire的数据库链接字符串").value, new SqlServerStorageOptions
                    {
                        CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
                        SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
                        QueuePollInterval = TimeSpan.Zero,
                        UseRecommendedIsolationLevel = true,
                        DisableGlobalLocks = true
                    }));

            // Add the processing server as IHostedService
            services.AddHangfireServer();
            //Hangfire的数据库可以跟应用程序共用一个库,也可以单独用一个数据库,里面大概不到10个表。
        }

        public static void UseMyHangFire(this IApplicationBuilder app, bool isUseDashboard = true)
        {
            if (isUseDashboard)
            {//是否使用web页面的后台管理
                //配置控制台页面路径,以及生产环境配置账号密码登录验证。
                app.UseHangfireDashboard("/hangfire", GlobalContext.HostingEnvironment.IsDevelopment() ? null : new DashboardOptions
                {
                    Authorization = new[] { new HangfireDashboardLoginFilter() }
                });
            }

            //定时数据库备份。
            RecurringJob.AddOrUpdate("Db_Backup",() => DbBackupTask.Db_Backup(), "0 0 6,12,18,23 * * ?");

            #region 测试几个
            if (false)
            {
                RecurringJob.AddOrUpdate("test_log", () => LogHelper.Info("测试:周期性打印日志", null), "0/5 * * * * *");//实际大概15秒执行一次日志打印。
                var jobId1 = BackgroundJob.Enqueue(() => Console.WriteLine("立马执行一次!" + DateTime.Now.GetDateTimeDesc()));
                var jobId2 = BackgroundJob.Schedule(() => Console.WriteLine("Delayed!5秒后执行一次。" + DateTime.Now.GetDateTimeDesc()), TimeSpan.FromSeconds(5));

                RecurringJob.AddOrUpdate("myrecurringjob", () => Console.WriteLine("反复执行,每5分钟!" + DateTime.Now.GetDateTimeDesc()), "*/5 * * * *");

                RecurringJob.RemoveIfExists("some-id");// It does not throw an exception when there is no such recurring job.
                                                       //RecurringJob.Trigger("some-id");//如果你想随时执行一个需重复间隔一定时间才执行的方法,那就用这个,不影响他原有的定期执行计划。
            }
            #endregion
        }

    }

定义个用于控制台需登录授权访问的类

一个控制台相关的类,用于设置进入页面的账号密码和身份验证,是个安全措施。

    public class HangfireDashboardLoginFilter : IDashboardAuthorizationFilter
    {
        public bool Authorize(DashboardContext context)
        {
            var httpContext = context.GetHttpContext();
            string header = httpContext.Request.Headers["Authorization"];//获取授权
            if (header == null)
                return AuthenicateLogin();
            //解析授权
            var authHeader = AuthenticationHeaderValue.Parse(header);
            var credentialBytes = Convert.FromBase64String(authHeader.Parameter);
            var credentials = Encoding.UTF8.GetString(credentialBytes).Split(new[] { ':' }, 2);
            var username = credentials[0];
            var password = credentials[1];
            //验证登录
            if (username == "账号" && password == "密码")
                return true;
            else
                return AuthenicateLogin();
            //跳转简单登录界面
            bool AuthenicateLogin()
            {
                httpContext.Response.StatusCode = 401;
                httpContext.Response.Headers.Append("WWW-Authenticate", "Basic realm=\"Hangfire Dashboard\"");
                context.Response.WriteAsync("Authenticatoin is required.");
                return false;
            }

        }
    }

添加服务注册和加入到中间件配置

在startup.cs 或 program.cs 中

//服务注册
//Add Hangfire services.
services.AddMyHangfire(Configuration);

//向请求处理管道中添加中间件
//使用Hangfire
app.UseMyHangFire();

app.UseRouting();

补充上面提到的定时备份数据库的任务类

    public class DbBackupTask
    {
        public static void Db_Backup()
        {
            var dal = new SystemDAL();
            var saveFolderPath = @"D:\DbBackup";
            using (var conn=dal.GetDbConnection())
            {
                saveFolderPath += $@"\{conn.Database}";
            }
            
            if (!Directory.Exists(saveFolderPath))
            {
                Directory.CreateDirectory(saveFolderPath);
            }

            var box = new DirectoryInfo(saveFolderPath);
            var files = box.GetFiles();
            if (files.Length > 20)
            {
                var delItems = files.Where(x => x.CreationTime < DateTime.Now.AddDays(-7));
                foreach (var item in delItems)
                {
                    item.Delete();
                }
            }
            dal.BackupDB(saveFolderPath);
        }
    }

使用时的一个注意点:

如果程序部署在iis,请务必查看下面这篇文章,以及HangFire官网相关的在IIS上部署相关的注意事项:

IIS 禁止自动回收 - PrintY - 博客园 (cnblogs.com)


更新于:2023.5.22

标签:Core,ASP,数据库,Hangfire,var,new,NET
From: https://www.cnblogs.com/idasheng/p/17419726.html

相关文章

  • Qemu仿真----(7)运行Ubuntu Core
    平台:ubuntu-22.04-desktop-amd64.对象:ubuntucore、qemu、raspberrypi、genericx86pc.文件:ubuntu-core-22-amd64.img.xz、ubuntu-core-22-arm64+raspi.img.xz详细介绍通过Qemu运行ubuntucore,简单介绍x64电脑和树莓派上的使用方法。1.账号1.1注册ubuntu账号由于Ubuntu......
  • 彻底理解EF Core(5)的运行机制,万字长文带你成长为团队中的EF Core专家
    彻底理解EFCore的运行机制,万字长文带你成长为团队中的EFCore专家1、将EF的ToTraceString移植为EFCore的ToQueryString2、从EFCore记录详细信息2.1、简单的日志记录2.2、响应EFCore事件2.3、使用事件计数器访问指标3、拦截EFCore的数据——拦截器4、查询拦截5、EFCore5中......
  • Asp.net MVC 3实例学习之ExtShop(六)——登录对话框
         登录对话框将使用jquery提供的对话框,所以不需要添加其它js文件。首先要为登录对话框添加一个表单模型。在Models目录下创建一个“AccountModels”类文件,然后添加一个Logon类,代码如下:1     public class LogOnModel2     {3      ......
  • ASP.NET Core之由配置系统与创建app所想到的
    先看文件配置的代码:ConfigurationBuilderconfigBuilder=newConfigurationBuiler();//典型的创建者模式configBuilder.AddJsonFile("config.json",option:false,reloadChange:false);//添加json配置文件,属于是创建者模式环节中的“配置创建者条件”的环节IconfigurationRootc......
  • 一步一步使用Ext JS MVC与Asp.Net MVC 3开发简单的CMS后台管理系统之用户管理(1)
    应用程序的基本框架已经搭建好了,现在要做的是完成一个个的功能模块。先从简单做起,完成用户管理模块,该模块主要功能是使用一个Grid显示用户信息,并使用RowEditing进行用户的编辑、添加操作。Grid的分页则在Grid顶部使用分页工具条实现,在工具条上还要添加3个按钮用来添加用户、删除用......
  • 一步一步使用Ext JS MVC与Asp.Net MVC 3开发简单的CMS后台管理系统之用户管理(4)
    现在来完成删除功能。目前的Grid,一次只能选择一行,也就是说,一次只能删除一行,不太方便,因而要设置成使用复选框选择,并允许多选的。在用户视图脚本文件中,添加以下配置项实现这个:"checkboxmodel",false,mode:"MULTI" 打开页面浏览,会看到如图29所示的效果,已经可以在最左边通过复选框进......
  • 一步一步使用Ext JS MVC与Asp.Net MVC 3开发简单的CMS后台管理系统之用户管理(3)
    昨天还有一个错误,CheckColumn的样式和图片没复制过来,造成最后一列的Checkbox显示不正确。在ExtJS包的examples\ux\css目录下打开CheckHeader.css文件,将文件里的全部样式定义复制到app.css中。然后修改将带背景图片的路径修改为“../images”。最后将image目录下的check.gif和unche......
  • 一步一步使用Ext JS MVC与Asp.Net MVC 3开发简单的CMS后台管理系统之用户管理(2)
    现在,创建视图,在Scripts\app\view目录下先创建目录Users,然后在该目录下创建View.js。要使用Grid显示用户信息,因而要从Grid面板派生出视图。定义的时候要注意视图的类名。还有就是一定要定义别名,因为在控制器中是使用widget方法创建的视图实例。如果不想定义别名,那就要修改创建实例的......
  • 一步一步使用Ext JS MVC与Asp.Net MVC 3开发简单的CMS后台管理系统之登录窗口调试
         现在可以对登录窗口进行调试了。     打开系统的首页页面文件,Views\Home目录下的Index.cshtml文件。要动态加载登录窗口,需要先设置好加载路径,因而在onReady函数上加入以下代码:Ext.Loader.setConfig({true,paths:{'Ext.ux':'scripts/extjs/ux'......
  • 一步一步使用Ext JS MVC与Asp.Net MVC 3开发简单的CMS后台管理系统之创建Viewport(1)
    忙活了那么久,终于进入正题,ExtJSMVC开发。开始前,先说说4.1.1的一点点变化。在4.1的时候,要先创建一个扩展于Ext.app.Application的类,然后用create创建它的实例来开始应用程序的。而在4.1.1,则可直接调用application方法开始执行应用程序,简化了。调用application方法,其参数是一个配置......