.Net Core 简单的Hangfire部署Demo

 

什么是Hangfire 

1.是分布式的后端作业调度框架,我们只需要关心业务逻辑代码,而不用关心调度机制持。
2.官方原文:在.NET和.NET Core应用程序中执行后台处理的简单方法。无需Windows服务或单独的进程。免费开源且可用于商业应用。Easy to set up, easy to use。
3.Hangfire支持 多种持久化方式 , 存储方式可支持sqlserver、redis,mongodb等等。
4.Hangfire支持所有类型的后台任务 - 短时间运行和长时间运行,CPU密集型和I/O密集型,一次性和周期性。

Hangfire组件的基本结构

核心组件:客户端,服务端,持久化存储。这些组件既可以分开部署在不同项目中也可以都部署在一个项目中。

客户端: 创建任务–>1、配置HangFire数据库连接 2、创建任务(在创建任务的时候HangFire会自动将任务序列化并存储到数据)。

服务端: 执行任务–>1、配置HangFire数据库连接 2、从HangFire数据库系统表读取客户端创建的任务然后开线程并行执行,任务之间不冲突。(服务端可宿主在Windows服务、控制台程序、IIS中…)。

数据库(持久化存储): HangFire程序框架表–>创建任务的时候HangFire会自动生成无需关心,但要注意如果采用现有的数据库,必须保证数据库中没有重名的表(aggregatedcounter、counter、distributedlock、hash、job、jobparameter、jobqueue、jobstate、list、server、set、state),数据库可采用 MySQL ,MSSQL,Redis等根据实际的需求来 

仪表盘(管理面板): 展示作业列表执行状态和结果等相关信息–>在.Net WebForm或.Net MVC 或.NetCore MVC网站程序对接

HangFire 自从1.6+版本后开始支持NetCore。 1.6.17-1.6.22之间基本为对Hangfire.Core的升级。


创建HangFireDemo

  1.创建个应用程序

.Net Core 简单的Hangfire部署Demo_第1张图片

 2.引用3个Nuguet包

Hangfire.AspNetCore                                           --Hangfire的组件的包
Hangfire.MySql.Core  /   Hangfire.Sqlserver        --Hangfire的持久化数据库的包
--权限包分为2种 任选其一 依赖项不同请自行选择
Hangfire.Dashboard.Authorization                       --Hangfire的权限控制包 (依赖项是owin和hangfire.Core) (目前没找到可视化界面的方法)
Hangfire.Dashboard.BasicAuthorization              --Hangfire被人二次封装的包。支持可视化界面的植入。支持core等

.Net Core 简单的Hangfire部署Demo_第2张图片

.Net Core 简单的Hangfire部署Demo_第3张图片.Net Core 简单的Hangfire部署Demo_第4张图片.Net Core 简单的Hangfire部署Demo_第5张图片

3.在管道中注入服务 (在Startup.cs  的ConfigureServices)

            //hangfire的任务需要数据库持久化
            //Hangfire.AspNetCore
            //Hangfire.MySql.Core  mysql引用 大小写敏感
            //Hangfire.SqlServer   sqlserver引用 大小写敏感

            //hangfire必须需要绑定一个持久化的连接数据。 官方推荐的是sqlserver,还有mg,mssql,pgsql,redis都是个人封装的
            //连接字符串必须加 Allow User Variables=true
            services.AddHangfire(x => x.UseStorage(new MySqlStorage(
                Configuration["ConnectionString"] ,
                new MySqlStorageOptions
                {
                    TransactionIsolationLevel = IsolationLevel.ReadCommitted, // 事务隔离级别。默认是读取已提交。
                    QueuePollInterval = TimeSpan.FromSeconds(15),             //- 作业队列轮询间隔。默认值为15秒。
                    JobExpirationCheckInterval = TimeSpan.FromHours(1),       //- 作业到期检查间隔(管理过期记录)。默认值为1小时。
                    CountersAggregateInterval = TimeSpan.FromMinutes(5),      //- 聚合计数器的间隔。默认为5分钟。
                    PrepareSchemaIfNecessary = true,                          //- 如果设置为true,则创建数据库表。默认是true。
                    DashboardJobListLimit = 50000,                            //- 仪表板作业列表限制。默认值为50000。
                    TransactionTimeout = TimeSpan.FromMinutes(1),             //- 交易超时。默认为1分钟。
                    TablePrefix = "Hangfire"                                  //- 数据库中表的前缀。默认为none
                }
                )));

ConnectionString是自己的连接字符串。放在配置文件中读取。连接字符串中必须加上  Allow User Variables=true
MySqlStorage 提供了多个重载方法。可以只注入连接字符串,不添加连接的特性配置。
其中 IsolationLevel 引用的包是    using System.Data;   


4.在管道后端使用

 主要是使用2个服务

 app.UseHangfireDashboard();   //使用hangfire面板
 app.UseHangfireServer();      //启动hangfire服务

 4.1)自定义配置hangfire面板  (在Startup.cs  的Configure)

 原生的面板如果不指定路径。默认的进入面板的地址是  (端口号:/hangfire),支持自定义进入hangfire的路径
 Hangfire.Dashboard.Authorization 包的自定义方法 (方法1)


            //添加面板的打开权限。不是所有人都可以打开面板。可以操作后台任务。
            app.UseHangfireDashboard("", new DashboardOptions
            {
               //方法1
               Authorization = new[]
               {
                 new BasicAuthAuthorizationFilterOptions
                 {
                    SslRedirect = false,          // 是否将所有非SSL请求重定向到SSL URL
                    RequireSsl = false,           // 需要SSL连接才能访问HangFire Dahsboard。强烈建议在使用基本身份验证时使用SSL
                    LoginCaseSensitive = false,   //登录检查是否区分大小写
                    Users = new[]
                    {
                        new BasicAuthAuthorizationUser
                        {
                            Login ="ycz",//用户名
                            PasswordClear="123456"
                            // Password as SHA1 hash
                            //Password=new byte[]{ 0xf3,0xfa,,0xd1 }
                        }
                    }
                 }
               },
               //方法2
                Authorization = new[]
               {
                    new HangfireAuthorizationFilter(){}
               },
              
            });

  --下图为 方法 2中启用的自定义规则类 。需要重写  IDashboardAuthorizationFilter 的 Authorize 方法

     //默认是只能内网访问。 需要重写这个方法。注入规则
     public class HangfireAuthorizationFilter : IDashboardAuthorizationFilter
     {

          //这里写自定义规则
          public bool Authorize([NotNull] DashboardContext context)
          {
             if (context.Request.LocalIpAddress.Equals("127.0.0.1") || context.Request.LocalIpAddress.Equals("::1"))
                return true;
             else
                return false;
           }
     }

  方法 1  是支持可视化界面的。  方法 2没有可视化界面但是开放了接口  IDashboardAuthorizationFilter  可以重写自定义规则 
  方法 1 和 方法 2 引用的包不一样,不可同时使用两种方法。需要注意
  Hangfire.Dashboard.BasicAuthorization (方法1的包)        Hangfire.Dashboard.Authorization  (方法2的包)

   而造成2种方法的差异性的就是。

 .Net Core 简单的Hangfire部署Demo_第6张图片
   启用面板时的 Authorization 对象在2个包中所支持的类不同,方法1 的包被进行了二次封装。

  --这个是 方法1 的Authorization 对象所支持的类型

--这个是 方法2 的Authorization 对象所支持的类型

 方法 1 和 方法 2 根据自己的需求。自行选择。

.Net Core 简单的Hangfire部署Demo_第7张图片.Net Core 简单的Hangfire部署Demo_第8张图片

  方法1 可视化界面   输入正确进入仪表盘。  输入错误会刷新界面 继续在当前登录页。 
  方法2 拦截器验证   通过验证直接进入仪表盘。 没通过验证返回 401
 

  4.2)自定义配置hangfire服务

//配置要处理的队列列表 ,如果多个服务器同时连接到数据库,会认为是分布式的一份子。可以通过这个配置根据服务器性能的按比例分配请求,不会导致服务器的压力。不配置则平分请求
      var jobOptions = new BackgroundJobServerOptions
      {
            Queues = new[] { "test", "default" },//队列名称,只能为小写
            WorkerCount = Environment.ProcessorCount * 5, //并发任务数  --超出并发数。将等待之前任务的完成  (推荐并发线程是cpu 的 5倍)
            ServerName = "hangfire1",//服务器名称
      };

      app.UseHangfireServer(jobOptions); //启动hangfire服务

    hangfire的服务是可以自定义任务的分发的。因为框架是支持分布式,可以根据任务量根据服务器的性能选择性的根据优劣比重进行分配任务,不然默认是平分任务。

 

5.配置完成

  起服务。  ip:端口号/hangfire  (没自定义面板配置是hangfire,不然是自己定义的路由)进入可视化面板

.Net Core 简单的Hangfire部署Demo_第9张图片

  .Net Core 简单的Hangfire部署Demo_第10张图片

 同时你的数据库里会创建12张表持久化你的任务

 

6.添加任务

  hangfire的任务分为多种       

  队列任务

  基于队列的任务处理是Hangfire中最常用的,客户端使用BackgroundJob类的静态方法Enqueue来调用,传入指定的方法(或是匿名函数),Job Queue等参数,会立即添加到队列中执行.
  在任务被持久化到数据库之后,Hangfire服务端立即从数据库获取相关任务并装载到相应的Job Queue下,在没有异常的情况下仅处理一次,
  若发生异常,提供重试机制,异常及重试信息都会被记录到数据库中,通过Hangfire控制面板可以查看到这些信息。
  任务执行不是同步的而是放到一个持久化队列中,然后将请求控制权返回给调用者,不会堵塞

BackgroundJob.Enqueue(() => Console.WriteLine($@"队列任务"));

  延时任务

  延迟(计划)任务跟队列任务相似,不是立即调用而是设定一个未来时间点再来执行。最小的延时类型为秒级别的

  BackgroundJob.Schedule(() => A(), TimeSpan.FromMinutes(1));

 定时任务

    定时循环任务执行:一行代码添加重复执行的任务,其内置了常见的时间循环模式,也可基于CRON表达式来设定复杂的模式 

  第一种 时间格式 (万能时间匹配)

  * 52 15 12 4 *  

  这种字符串就是corn表达式 格式是  {秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)} 空格间隔
  *代表的是通配 任意  ?是只有在星期的时候可以占位的符号 代表这个时间不在意的,不会影响匹配   

 * 52 15 12 4 ?

   第二种 时间格式 (循环时间匹配)
   Corn.Minutely          是定时任务最小的循环单位,代表每分钟执行一次。还支持的 年 月 日 小时的循环执行

   第三种 时间格式 (自定义时间)
   Cron.Daily(18,36)    支持多种重载方法 第一个参数是小时,第二个参数是分钟。
   (这种方法的本质其实也是底层使用的Cron表达式 ,不过这里只有5位/6位和cron定义的最多7位有差异。应该是省略了年)

  
   如果是要指定的时间执行要注意时区问题。默认的是UTC的时区。想要使用当前时间则需要指定时间类型 TimeZoneInfo.Local

 RecurringJob.AddOrUpdate("1",() => A(), "* 52 15 12 4 *");   //每年的4月12号15点52分任意秒执行 没加时区 小时+8
 RecurringJob.AddOrUpdate("2",() => A(), Cron.Minutely);      //每分钟执行一次。
 RecurringJob.AddOrUpdate("3",() => A(), Cron.Daily(18,36),TimeZoneInfo.Local);  //每天18点36分 当前时区

  延续性任务执行 

  延续性任务类似于.NET中的Task,可以在第一个任务执行完之后紧接着再次执行另外的任务:

 BackgroundJob.ContinueWith("1", () => B());

 延续性批处理 和 批处理

 pro版本  (需要商业授权和收费) 这里实现的效果应该和上面雷同 (这里没有自己具体测试下面的功能)

 //延续性批处理 
 BatchJob.StartNew(x =>
            {
                x.Enqueue(() => Console.WriteLine("Job 1"));
                x.Enqueue(() => Console.WriteLine("Job 2"));
            });

 //批处理
 BatchJob.ContinueWith(batchId, x =>
            {
                x.Enqueue(() => Console.WriteLine("Last Job"));
            });

 里面的方法可以自定义多种类型我这里只是这三种了

.Net Core 简单的Hangfire部署Demo_第11张图片


个人总结:

   1.只有定时任务和延续性任务支持自定义编号,如果不自己定义就会默认将方法名设置为编号  在可视化界面中

 2.所有的记录方法都会被持久化到数据库里。如果关闭了服务。下次再开启。之前的周期性任务依然会存在 依然会被执行.Net Core 简单的Hangfire部署Demo_第12张图片

3.冗余规则(因为持久化的原因 服务的调用可能会重复执行定时任务,所以针对规则选择定时任务的位置启动在哪)

我定义了6个定时任务。不断重复启动,但是任务列表中只有这3个定时任务。说明规则冗余规则是:

无编号下 取方法为编号。同编号的任务只会存在一条,而时间取最后执行的那次时间为准
有编号下 编号相同不会重复存在定时任务。

 

本文参考链接:https://blog.csdn.net/long870294701/article/details/87810621

 


 

你可能感兴趣的:(学习总结,.Net,Core,Hangfire,Hangfire时区,Hangfire权限)