天天看點

【.NET Core】Hangfire入門

中文文档:

https://www.mianshigee.com/tutorial/Hangfire-zh-official/readme.md

案例源码:

https://gitee.com/core-demo/hangfire

Demo

1、安装Nuget

<PackageReference Include="Hangfire.AspNetCore" Version="1.7.28" />
<PackageReference Include="Hangfire.Core" Version="1.7.28" />
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
<PackageReference Include="Hangfire.MySqlStorage" Version="2.0.3" />
           

添加数据库连接配置:

"ConnectionStrings": {
    "DefaultConnection": "Data Source=xxxxx;User Id=root;Password=xxxxx;Database=hangfireDB;Port=3306;default command timeout=100;Connection Timeout=30;Charset=utf8mb4;Allow User Variables=true;IgnoreCommandTransaction=true"
  }
           

2、Hangfire服务、中间件

using Hangfire;
using Hangfire.Dashboard.BasicAuthorization;
using Hangfire.MySql;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System;

/// <summary>
/// Hangfire扩展
/// </summary>
public static class HangfireStartupExtensions
{
    /// <summary>
    /// 注册Hangfire相关服务
    /// </summary>
    /// <param name="services"></param>
    /// <param name="connectionString"></param>
    public static void AddHangfire(this IServiceCollection services, string connectionString)
    {
        if (services == null) throw new ArgumentNullException(nameof(services));
        services.AddHangfire(configuration => configuration
        .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)//此方法 只初次创建数据库使用即可
                        .UseSimpleAssemblyNameTypeSerializer()
        .UseRecommendedSerializerSettings()
        .UseStorage(new MySqlStorage(connectionString, new MySqlStorageOptions
        {
            TransactionIsolationLevel = (System.Transactions.IsolationLevel?)System.Data.IsolationLevel.ReadCommitted, //事务隔离级别。默认是读取已提交
            QueuePollInterval = TimeSpan.FromSeconds(5), //- 作业队列轮询间隔。默认值为15秒。
            JobExpirationCheckInterval = TimeSpan.FromHours(1),
            CountersAggregateInterval = TimeSpan.FromMinutes(5),
            PrepareSchemaIfNecessary = true, // 如果设置为true,则创建数据库表。默认是true
            DashboardJobListLimit = 50000,
            TransactionTimeout = TimeSpan.FromMinutes(1),
            TablesPrefix = "Hangfire",

        }))
        .UseActivator(new JobActivator(services.BuildServiceProvider())));//依赖注入
        services.AddHangfireServer();
    }
    /// <summary>
    /// 注册Hangfire中间件
    /// </summary>
    /// <param name="app"></param>
    public static void UseHangfire(this IApplicationBuilder app)
    {
        if (app == null) throw new ArgumentNullException(nameof(app));
        //WorkerCount(默认20个):需要限制一下,否则会占用过多的数据库连接
        app.UseHangfireServer(new BackgroundJobServerOptions { WorkerCount = 2 }); //配置服务
        app.UseHangfireDashboard("/hangfire", DashboardOptions); //配置面板
    }
    private static DashboardOptions DashboardOptions
    {
        get
        {
            var filter = new BasicAuthAuthorizationFilter(
                new BasicAuthAuthorizationFilterOptions
                {
                    SslRedirect = false,
                    RequireSsl = false,
                    LoginCaseSensitive = false,
                    Users = new[]
                    {
                    new BasicAuthAuthorizationUser
                    {
                        Login = "fan", //可视化的登陆账号
                        PasswordClear = "123456" //可视化的密码
                    }
                    }
                });
            return new DashboardOptions
            {
                Authorization = new[] { filter }
            };
        }
    }
}
           

3、JobActivator

Job是通过JobActivator创建,如果job依赖其他服务,需要重写JobActivator

/// <summary>
/// Hangfire Job依赖注入
/// </summary>
public class JobActivator : Hangfire.JobActivator
{
    private IServiceProvider _serviceProvider;

    public JobActivator(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public override object ActivateJob(Type type)
    {
        using var scope = _serviceProvider.CreateScope();
        return scope.ServiceProvider.GetService(type);
    }
}
           

4、注册服务、中间件

//ConfigureServices
services.AddHangfire(Configuration.GetConnectionString("DefaultConnection"));
//Configure
app.UseHangfire();
           

5、封装助手类,用户创建、删除周期任务

/// <summary>
    /// 后台任务操作
    /// </summary>
    public interface IBackgroundJobManager
    {
        /// <summary>
        /// 创建周期性任务
        /// </summary>
        /// <param name="jobID"></param>
        /// <param name="cronExp"></param>
        void CreateRecurringJob(string jobID, string cronExp, Type jobType, MethodInfo jobMethod, params object[] args);

        /// <summary>
        /// 删除任务
        /// </summary>
        /// <param name="jobID"></param>
        void DeleteJob(string jobID);
    }
    public class BackgroundJobManager : IBackgroundJobManager
    {
        public void CreateRecurringJob(string jobID, string cronExp, Type jobType, MethodInfo jobMethod, params object[] args)
        {
            var manager = new RecurringJobManager();
            manager.AddOrUpdate(jobID, new Hangfire.Common.Job(jobType, jobMethod, args), cronExp);
        }

        public void DeleteJob(string jobID)
        {
            var manager = new RecurringJobManager();
            manager.RemoveIfExists(jobID);
        }
    }
           

注册:

builder.Services.AddScoped<IBackgroundJobManager, BackgroundJobManager>();
           

6、客户端

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly IBackgroundJobManager _backgroundJobManager;
    public HomeController(ILogger<HomeController> logger, IBackgroundJobManager backgroundJobManager)
    {
        _logger = logger;
        _backgroundJobManager= backgroundJobManager;
    }

    public IActionResult Index()
    {
        return View();
    }
    /// <summary>
    /// 创建周期job
    /// </summary>
    /// <returns></returns>
    public IActionResult CreateJob()
    {
        var jobType = typeof(MyJob);
        var jobMethod = jobType.GetMethod("ExecuteJob");
        string cronExp = "0 */2 * * * ?";//每隔两分钟执行1次
        _backgroundJobManager.CreateRecurringJob($"job-1", cronExp, jobType, jobMethod, 1);//最后一个参数是jobMethod的形参
        return Content("success");
    }
    /// <summary>
    /// 删除job
    /// </summary>
    /// <returns></returns>
    public IActionResult DeleteJob()
    {
        _backgroundJobManager.DeleteJob($"job-1");
        return Content("success");
    }
}
           

7、job

public class MyJob
    {
        private readonly ILogger<MyJob> _logger;
        public MyJob(ILogger<MyJob> logger)
        {
            _logger = logger;
        }
        public void ExecuteJob(int arg)
        {
            _logger.LogInformation($"执行job,参数:{arg}");
        }
    }
           

注册job:

builder.Services.AddScoped<MyJob>();
           

7、启动项目

查看Hangfire仪表盘:http://xxxx/hangfire

查看数据库,生成了如下表:

【.NET Core】Hangfire入門

每隔两分钟,输出日志:

【.NET Core】Hangfire入門