三沣开发知识 购物 网址 游戏 小说 歌词 地图 快照 开发 股票 美女 新闻 笑话 | 汉字 软件 日历 阅读 下载 图书馆 编程 租车 短信 China
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题
autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程 CSS/HTML/Xhtml
html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
站长资讯 .NET新手 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA VisualStudio ASP.NET-MVC .NET控件开发 EntityFramework WinRT-Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动 Html-Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP OracleERP DynamicsCRM K2 BPM 信息安全 企业信息 Android开发 iOS开发 WindowsPhone WindowsMobile 其他手机 敏捷开发 项目管理 软件工程 SQLServer Oracle MySQL NoSQL 其它数据库 Windows7 WindowsServer Linux
  IT知识库 -> 架构设计 -> Abp后台工作者类使用hangfire -> 正文阅读
 

[架构设计]Abp后台工作者类使用hangfire

Abp后台工作者类使用hangfire 一、Abp中的后台工作及后台工作者类
请阅读这篇文章
二 、Abp官方实现的缺点
Abp官方实现方式很简单,也很容易上手,但缺点是工作者类依赖了具体的基类(PeriodicBackgroundWorkerBase),就会存在应用程序耦合。

为什么会耦合呢,假设以后想采用HangFire或Quartz.NET来调度工作者,我们就需要把所有工作类的基类进行修改,这不利于系统的维护和可扩展,而且采用官方实现无法监测和管控工作者。
三、开始改造
1、核心库

 要消除工作者类对具体调度类的依赖,则只能让后台工作者类继承自不含调度实现的基类(BackgroundWorkerBase)或直接实现接口(IBackgroundWorker)。我定义了一个泛型基类(BackgroundWorker<T>),该基类继承ABP核心库的BackgroundWorkerBase,同时该基类必须实现我自定定义的IBackgroundWorkerDo接口。
BackgroundWorker<T>:所有后台工作者类都该继承的基类,加泛型参数的目的是Hangfire的RecurringJob.AddOrUpdate<T>方法在创建轮询任务时必须知道它该调用哪个类的哪个方法
IBackgroundWorkerDo:  约束所有后台工作者类必须实现DoWork,配合泛型参数,Hangfire的轮询任务便可以知道T类型一定会有一个DoWork方法,然后在RecurringJob.AddOrUpdate<T>的方法体中便可以调用T类型实的DoWork方法
WorkerConfig类: 每个后台工作者都应该有一个唯一的标识,执行间隔时间,这样轮询代理类才知道如何处理
IBackgroudWorkerProxy: 代替后台工作者类执行其DoWork方法,所有轮询调度类都应该实现该接口

    /// <summary>
    /// 所有的后台工作者类都应实现该接口
    /// </summary>
    public interface IBackgroundWorkerDo
    {
        /// <summary>
        /// 执行具体的任务
        /// </summary>
        void DoWork();
    }


    /// <summary>
    /// 所有后台工作者类都应继承该类
    /// </summary>
    public abstract class BackgroundWorker<T> : BackgroundWorkerBase, IBackgroundWorkerDo where T : IBackgroundWorkerDo
    {
        protected readonly IBackgroudWorkerProxy _workProxy;
        protected readonly WorkerConfig _config;
        protected BackgroundWorker(IBackgroudWorkerProxy workProxy, WorkerConfig config)
        {
            _workProxy = workProxy;
            _config = config;
        }
        /// <summary>
        /// 任务启动
        /// </summary>
        public override void Start()
        {
            Logger.Debug("轮询任务启动");
            _workProxy.Excete<T>(DoWork, _config); //主要指定当前任务类,不然hangfire无法调用,不然可以移到父类去
        }
        /// <summary>
        /// 具体的任务执行
        /// </summary>
        public abstract void DoWork();
    }


    /// <summary>
    /// 工作任务配置
    /// </summary>
    public class WorkerConfig
    {
        /// <summary>
        /// 轮询秒数
        /// </summary>
        public int IntervalSecond { get; set; }
        /// <summary>
        /// 工作唯一编号
        /// </summary>
        public string WorkerId { get; set; }
    }


    public interface IBackgroudWorkerProxy
    {
        /// <summary>
        /// 执行
        /// </summary>
        /// <param name="method"></param>
        void Excete<T>(Action method, WorkerConfig config) where T : IBackgroundWorkerDo;
    }

以上便是解耦的核心代码,在核心代码中,仿照Abp官方的PeriodicBackgroundWorkerBase类提供了一个基于Timer的轮询调度实现:

   public class PeriodicWorkerPxoxy : IBackgroudWorkerProxy
    {
        private Action ExetuteMethod { get; set; }
        protected readonly AbpTimer Timer;
        public PeriodicWorkerPxoxy(AbpTimer timer)
        {
            Timer = timer;
            Timer.Elapsed += Timer_Elapsed;
        }

        private void Timer_Elapsed(object sender, EventArgs e)
        {
            try
            {
                DoWork();
            }
            catch (Exception ex)
            {

            }
        }

        public void Excete<T>(Action method, WorkerConfig config) where T: IBackgroundWorkerDo
        {
            ExetuteMethod = method;
            Timer.Period = config.IntervalSecond*1000;//将传入的秒数转化为毫秒
            Timer.Start();
        }

        protected  void DoWork()
        {
            ExetuteMethod();
        }
    }

作为一个核心模块,所以还需要定义一个模块启动配置文件

public class FastWorkWorkerPxoxyModule : AbpModule
    {
        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
        }
        public override void PreInitialize()
        {
            IocManager.RegisterIfNot<IBackgroudWorkerProxy, PeriodicWorkerPxoxy>();
        }
    }

核心库解决方案图如下,(记住要引用Abp核心库)

在需要的项目中引入该Dll,然后按照模块启动配置依赖进行配置

    [DependsOn(typeof(AbpZeroCoreModule), typeof(AbpZeroLdapModule), typeof(AbpAutoMapperModule), typeof(FastWorkWorkerPxoxyModule))]
    public class FastWorkCoreModule : AbpModule
    {
          ...
    }

后台工作者类示例:

namespace ORS.FastWork.Core.Sms
{
    /// <summary>
    /// 清理短信日志
    /// </summary>
    public class SmsWorker : BackgroundWorker<SmsWorker>, ISingletonDependency
    {
        private readonly IRepository<SmsSendLog, long> _smsLogRepository;
        public SmsWorker(IRepository<SmsSendLog, long> smsLogRepository,IBackgroudWorkerProxy workMiddleware) : base(workMiddleware, new WorkerConfig { IntervalSecond=60,WorkerId="smsworker"})
        {
            _smsLogRepository = smsLogRepository;
        }
        public override void DoWork()
        {
            //_smsLogRepository.Insert(new SmsSendLog { IsOk = true, Content = "轮询任务创建的", CreationTime = DateTime.Now });
        }
    }
}

2、HangFire实现
主要的类有两个,一个是启动配置,一个实现了IBackgroudWorkerProxy接口,解决方案目录如下:

解决方案记得引用上面定义好的核心库,Hangfire实现轮询的代码如下:

  public class HangfireWorkerPxoxy : IBackgroudWorkerProxy
    {
        public HangfireWorkerPxoxy()
        {

        }
        private WorkerConfig Config { get; set; }
        public void Excete<T>(Action method, WorkerConfig config) where T: IBackgroundWorkerDo
        {
            Config = config;
            string workerId = config.WorkerId;
            string cron = Cron.MinuteInterval(config.IntervalSecond/60);
            RecurringJob.AddOrUpdate<T>(config.WorkerId, (t)=>t.DoWork(), cron,TimeZoneInfo.Local);
            RecurringJob.Trigger(config.WorkerId);
        }
    }

 模块启动文件中的代码很关键,当后台工作采用了Hangfire来调度时(即在web模块的启动文件中使用了 Configuration.BackgroundJobs.UseHangfire(...)),则后台工作者类的调度也将由我们核心库中的PeriodicWorkerPxoxy变更为Hangfire来接管

 public class HangFireWorkerModule : AbpModule
 {
        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
        }
        public override void PreInitialize()
        {
            IocManager.RegisterIfNot<IBackgroudWorkerProxy, HangfireWorkerPxoxy>();
        }
        public override void PostInitialize()
        {
            //判断是否启用了hangfire,如果启用了,则将IBackgroudWorkerProxy的实例改为hangfire
            var hangfireConfig = IocManager.Resolve<IAbpHangfireConfiguration>();
            if (hangfireConfig?.Server!= null) {
                IocManager.IocContainer.Register(Component.For<IBackgroudWorkerProxy>().ImplementedBy<HangfireWorkerPxoxy>().IsDefault());
            }
        }
}

 在Web项目中引用该项目,然后在模块启动中加入对该模块的依赖

在PostInitialize方法中向后台工作管理类加入具体的工作

最终效果如下:

 

3.进一步优化
该方案目前已在我们公司的项目中投入使用,由于时间和精力关系,我个人没有对该方案进行进一步优化。在web模块启动文件中,还是需要做两步工作:1.引用了dll 2.启动文件上标注依赖关系,每增加一种轮询调度方式我们都需要重复这两步,如果想做得更灵活的话,可以弄成插件模块(拷入dll到站点PlugIns目录,然后再后台设置一下即可),下一篇文章我会以短信网关插件实战来演示Abp插件模块的妙用。
  架构设计 最新文章
spring boot实现ssm(2)功能
java 企业站源码 兼容手机平板PC 自适应响应
Serverless无服务应用架构纵横谈
理论篇:关注点分离(Separation of concern
Struts 2 入门
spring boot实现ssm(1)功能
函数指针
GPS部标监控平台的架构设计(十一)
Warrior!之家与Warrior!博客网站发布
一个高性能、轻量级的分布式内存队列系统
上一篇文章      下一篇文章      查看所有文章
加:2017-05-04 15:22:50  更:2017-05-16 03:04:38 
 
技术频道: 站长资讯 .NET新手区 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA Visual Studio ASP.NET MVC .NET控件开发 Entity Framework WinRT/Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动设计 Html/Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP Oracle ERP Dynamics CRM K2 BPM 信息安全 企业信息化其他 Android开发 iOS开发 Windows Phone Windows Mobile 其他手机开发 敏捷开发 项目与团队管理 软件工程其他 SQL Server Oracle MySQL NoSQL 其它数据库 Windows 7 Windows Server Linux
脚本语言: vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题 autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程
网站开发: CSS/HTML/Xhtml html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年7日历
2018-7-22 16:53:31
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT知识库