Hangfire 在asp.net core环境的使用

hf被定义为分布式后台服务,更加相似job做业的服务
作做业的插件有quartz.net,JobScheduler 等
固然,都有一些分别和适用的场景。
1.安装
须要安装
Hangfire.Core
Hangfire.AspNetCore
Hangfire.SqlServer
关于数据库存储工具,能够根据场景去选择安装
例如mysql 的,须要安装 Hangfire.MySql (mysql不少第三方写,因此使用时主要使用环境)
Redis放入 Hangfire.Redis
redis是官方做者去更新,因此这些使用能够直接看官网
2.配置
asp.net core主要是startup配置DI组件。
官网也有说,列举一下mysql

  // Add Hangfire services.
            services.AddHangfire(configuration => configuration
           .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
           .UseSimpleAssemblyNameTypeSerializer()
           .UseRecommendedSerializerSettings()
           .UseSqlServerStorage(Configuration.GetConnectionString("default"), new SqlServerStorageOptions
           {
               CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
               SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
               QueuePollInterval = TimeSpan.Zero,
               UseRecommendedIsolationLevel = true,
               UsePageLocksOnDequeue = true,
               DisableGlobalLocks = true
           }));

      services.AddHangfireServer();

关键是这个链如何配,UseSqlServerStorage专门读取hangfire会写入哪一个数据库,若是用如今的业务数据库,hangfire的表会写进去的,也能够设计分开来存放,例如hangfire的DB,集中去管理。固然通常小的项目,直接跟业务数据库,集中而独立的架构。redis

Configure里面的配置sql

var jobOptions = new BackgroundJobServerOptions
            {
                Queues = new[] { "back", "front", "default" },//队列名称,只能为小写
                WorkerCount = Environment.ProcessorCount * 5, //并发任务数
                ServerName = "conference hangfire1",//服务器名称
            };

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

            app.UseHangfireDashboard();//启动hangfire面板
            backgroundJobs.Enqueue(() => Console.WriteLine("Hangfire 服务器已启动"));

            app.UserHangfireAdminService(service); //这个是本身写的服务扩展

jobOptions若是不配置,会有本身默认的名称,例如服务器会读取你当前系统的名称,队列那些会读取对应服务器的程序集名称。数据库

3.写服务api

完成了第一二步,这里看这个做业如何写服务器

public static class HangfireAdminService
    {
        private static BackgroundJobServer _server;

        /// <summary>
        /// 使用后台做业
        /// </summary>
        /// <param name="app"></param>
        /// <param name="service"></param>
        /// <param name="client"></param>
        /// <returns></returns>
        public static IApplicationBuilder UserHangfireAdminService(this IApplicationBuilder app,
            IConferenceService service)
        {
            var mcfg = service.MailConfigDefault();
            BackgroundJob.Enqueue(() => Console.WriteLine($"测试单个做业: {DateTime.Now}"));
            RecurringJob.AddOrUpdate(
                () =>
               Console.WriteLine($"测试循环做业: {DateTime.Now}"), Cron.Minutely
            );

            BackgroundJob.Schedule(() => Console.WriteLine($"测试延迟做业: {DateTime.Now}"), TimeSpan.FromMinutes(1));

            return app;
        }
    }

这个是刚才configure里面的方法。 能够写成一个IApplicationBuilder的扩展方法,加进管道
这样服务器启动时,就会启动里面的服务。
若是Job做业须要调用一个后台服务,就不能直接在里面_service.Log这样去调用方法了,由于处于不一样的线程方式。因此job调后台,能够这样操做
举例,这是个api发邮件的方法架构

/// <summary>
        /// 发送邮件
        /// </summary>
        /// <param name="mail"></param>
        [HttpPost]
        [Route("SendPwd")]
        public MsgResult<bool> SendPwd(MailConfigDto mail)
        {
            MsgResult<bool> result = new MsgResult<bool>(ResultCode.Success);
            UserAccountDto user = null;
            try
            {
                MailConfigDto defaultMail = _service.MailConfigDefault();

                user = _service.UserDtoById(mail.ExtensionId);
                defaultMail.Body = $"用户注册成功!登陆名是:{user.UserName},登陆密码是:{user.Password},注册类型是:{user.CustomerProfileName}";
                defaultMail.Subject = $"用户:{user.Name}注册成功!";
                List<KeyValuePair<string, string>> To = new List<KeyValuePair<string, string>>() {
                    new KeyValuePair<string, string>(user.Name,user.Email)
                };
                defaultMail.To = To;
                SendEmail(defaultMail);
                BackgroundJob.Enqueue<IConferenceService>((s) =>
                 s.LogAdd("注册成功", $"用户{user.Name}注册成功,已发送邮件", OPLog.AdminLogin)
                  );
            }
            catch (Exception ex)
            {
                result = new MsgResult<bool>(ResultCode.Exception, ex.Message);
            }

            return result;

        }

关键点, BackgroundJob.Enqueue<IConferenceService>((s) =>s.LogAdd());
Enqueue有个泛型的重载,这里等因而依赖注入的方式,由于在全局autofac配置过
IConferenceService是指向ConferenceService服务的,因此这里注入了Enqueue<IConferenceService>接口,只能是接口,才可让DI生效。
so, s.LogAdd表明了接口里面的方法。这样Enqueue里面就能够调用后台自定义的服务了并发

4.总结,固然还有不少细节没谈,不过这样基本的配置和使用,已经知足软件的平常用途了。
补充一点,经常使用的三种方式的特色,
当即执行,完过后会自动销毁,固然,失败了按默认的1分钟后会从新尝试,直到成功了
延迟执行,这个等于制定了计划的执行时间,这里最少时间是按分钟算,因此这里不能按用秒甚至毫秒作计算时间的任务。
循环执行,循环执行独立一个方法 RecurringJob。若是大类分,前2个是一个后台做业类,这个独立的类。循环执行某次进程若是失败了,也不会影响总体的循环效果,只是失败的进程也会按整体的规则,1分钟后从新尝试失败的进程。app

固然还有其余的,例如批量处理,延续,批量延续等asp.net

相关文章
相关标签/搜索