1。什么是ScheduleMaster ScheduleMaster是分布式任务调度系统。简称:集中任务调度系统,最简单的理解ScheduleMaster,就是对不同的系统里面的调度任务做统一管理的框架。 例如我们现在有多个系统,每个系统针对自己处理不同的业务场景。衍生出自己的调度任务,想象一下,如果每个系统人为去维护,那随着调度任务越来越多,人是崩溃的吧,可见维护和技术成本是巨大的,这时我们需要选择分布式任务系统框架做统一的管理 当然有目前有很多相对优秀分布式任务系统框架,我们主要学习ScheduleMaster2。使用ScheduleMaster 1。首先我们需要使用NETCorewebApi创建几个模拟的微服务,分别为考勤、算薪、邮件、短信 2。下载开源的ScheduleMaster,并且使用ScheduleMaster调度我们的微服务接口sqlserver:PersistSecurityInfoFUserIDPassword123456;InitialCServer。postgresql:SPort5432;DUserIPassword123456;PMaxPoolSize20;mysql:DataSDUserIDPassword123456;CharSetutf8mb4;port3306;TreatTinyAsBooleantrue修改Host的配置文件和支持的数据库,框架默认使用Mysql 修改Web的配置文件和支持的数据库,框架默认使用Mysql 3。进入Hos。ScheduleMaster。Web项目的发布目录,dotnetHos。ScheduleMaster。Web。dll启动项目,此时会生成数据库登录账号:admin 密码:111111 4。进入Hos。ScheduleMaster。QuartzHost项目的发布目录,执行命令,启动项目dotnetHos。ScheduleMaster。QuartzHost。dllurlshttp::300031。配置Http调度任务 5。准备就绪后,使用后台查看节点管理,可以看到web主节点30000和任务调度的接口30002已经在运行 6。使用任务列表菜单,创建定时调度任务,配置基础信息和元数据配置,然后点击保存就开始执行任务 2。配置程序集调度任务 1。创建一个类库,安装ScheduleMaster库,创建一个类继承TaskBase,实现抽象方法,然后编译程序集namespaceTaskExcuteService{classAssemblyTask:TaskBase{publicoverridevoidRun(TaskContextcontext){context。WriteLog(程序集任务);}}} 2。找到debug目录,去掉Base程序集,然后添加为压缩文件 3。在web界面找到任务配置,选择程序集进行基本配置,配置元数据,输入程序集名称,然后输入类,并将程序集上传,保存就可以运行了3。使用Api接入任务 为了方便业务系统更好的接入调度系统,ScheduleMaster创建任务不仅可以在控制台中实现,系统也提供了WebAPI供业务系统使用代码接入,这种方式对延时任务来说尤其重要。1。APIServer对接流程在控制台中创建好专用的API对接用户账号。使用对接账号的用户名设置为httpheader中的msauthuser值。使用经过哈希运算过的秘钥设置为httpheader中的msauthsecret值,计算规则:按{用户名}{hash(密码)}{用户名}的格式拼接得到字符串str,然后再对str做一次hash运算即得到最终秘钥,hash函数是小写的32位MD5算法。使用form格式发起http调用,如果非法用户会返回401Unauthorized。HttpClientclientnewHttpClient();client。DefaultRequestHeaders。Add(msauthuser,admin);client。DefaultRequestHeaders。Add(msauthsecret,SecurityHelper。MD5(34;admin{SecurityHelper。MD5(111111)}}admin)); 所有接口采用统一的返回格式,字段如下: 参数名称 参数类型 说明 Success bool 是否成功 Status int 结果状态,0请求失败1请求成功2登录失败3参数异常4数据异常 Message string 返回的消息 Data object 返回的数据2。创建程序集任务 使用API创建任务的方式不支持上传程序包,所以在任务需要启动时要确保程序包已通过其他方式上传,否则会启动失败。接口地址:http:yourip:30000apitaskcreate请求类型:POST参数格式:applicationxwwwformurlencoded返回结果:创建成功返回任务id参数列表: 参数名称 参数类型 是否必填 说明 MetaType int 是 任务类型,这里固定是1 Title string 是 任务名称 RunLoop bool 是 是否按周期执行 CronExpression string 否 cron表达式,如果RunLoop为true则必填 AssemblyName string 是 程序集名称 ClassName string 是 执行类名称,包含完整命名空间 StartDate DateTime 是 任务开始时间 EndDate DateTime 否 任务停止时间,为空表示不限停止时间 Remark string 否 任务描述说明 Keepers List 否 监护人id Nexts List 否 子级任务id Executors List 否 执行节点名称 RunNow bool 否 创建成功是否立即启动 Params List 否 自定义参数列表,也可以通过CustomParamsJson字段直接传json格式字符串 ScheduleParam: 参数名称 参数类型 是否必填 说明 ParamKey string 是 参数名称 ParamValue string 是 参数值 ParamRemark string 否 参数说明HttpClientclientnewHttpClient();ListKeyValuePairstring,stringargsnewListKeyValuePairstring,string();args。Add(newKeyValuePairstring,string(MetaType,1));args。Add(newKeyValuePairstring,string(RunLoop,true));args。Add(newKeyValuePairstring,string(CronExpression,3308?));args。Add(newKeyValuePairstring,string(Remark,ByXunitTesterCreated));args。Add(newKeyValuePairstring,string(StartDate,DateTime。Today。ToString(yyyyMMddHH:mm:ss)));args。Add(newKeyValuePairstring,string(Title,程序集接口测试任务));args。Add(newKeyValuePairstring,string(AssemblyName,Hos。ScheduleMaster。Demo));args。Add(newKeyValuePairstring,string(ClassName,Hos。ScheduleMaster。Demo。Simple));args。Add(newKeyValuePairstring,string(CustomParamsJson,〔{ParamKey:k1,ParamValue:1111,ParamRemark:r1},{ParamKey:k2,ParamValue:2222,ParamRemark:r2}〕));args。Add(newKeyValuePairstring,string(Keepers,1));args。Add(newKeyValuePairstring,string(Keepers,2));args。Add(newKeyValuePairstring,string(Nexts,));args。Add(newKeyValuePairstring,string(Executors,));HttpContentreqContentnewFormUrlEncodedContent(args);varresponseawaitclient。PostAsync(http:localhost:30000apiTaskCreate,reqContent);varcontentawaitresponse。Content。ReadAsStringAsync();Debug。WriteLine(content);3。创建HTTP任务接口地址:http:yourip:30000apitaskcreate请求类型:POST参数格式:applicationxwwwformurlencoded返回结果:创建成功返回任务id参数列表: 参数名称 参数类型 是否必填 说明 MetaType int 是 任务类型,这里固定是2 Title string 是 任务名称 RunLoop bool 是 是否按周期执行 CronExpression string 否 cron表达式,如果RunLoop为true则必填 StartDate DateTime 是 任务开始时间 EndDate DateTime 否 任务停止时间,为空表示不限停止时间 Remark string 否 任务描述说明 HttpRequestUrl string 是 请求地址 HttpMethod string 是 请求方式,仅支持GETPOSTPUTDELETE HttpContentType string 是 参数格式,仅支持applicationjson和applicationxwwwformurlencoded HttpHeaders string 否 自定义请求头,ScheduleParam列表的json字符串 HttpBody string 是 如果是json格式参数,则是对应参数的json字符串;如果是form格式参数,则是对应ScheduleParam列表的json字符串。 Keepers List 否 监护人id Nexts List 否 子级任务id Executors List 否 执行节点名称 RunNow bool 否 创建成功是否立即启动HttpClientclientnewHttpClient();ListKeyValuePairstring,stringargsnewListKeyValuePairstring,string();args。Add(newKeyValuePairstring,string(MetaType,2));args。Add(newKeyValuePairstring,string(RunLoop,true));args。Add(newKeyValuePairstring,string(CronExpression,2208?));args。Add(newKeyValuePairstring,string(Remark,ByXunitTesterCreated));args。Add(newKeyValuePairstring,string(StartDate,DateTime。Today。ToString(yyyyMMddHH:mm:ss)));args。Add(newKeyValuePairstring,string(Title,Http接口测试任务));args。Add(newKeyValuePairstring,string(HttpRequestUrl,http:localhost:56655api1。0valuejsonpost));args。Add(newKeyValuePairstring,string(HttpMethod,POST));args。Add(newKeyValuePairstring,string(HttpContentType,applicationjson));args。Add(newKeyValuePairstring,string(HttpHeaders,〔〕));args。Add(newKeyValuePairstring,string(HttpBody,{Posts:〔{PostId:666,Title:tester,Content:testtesttest}〕,BlogId:111,Url:qweqrrttryrtyrtrtrt}));HttpContentreqContentnewFormUrlEncodedContent(args);varresponseawaitclient。PostAsync(http:localhost:30000apiTaskCreate,reqContent);varcontentawaitresponse。Content。ReadAsStringAsync();Debug。WriteLine(content);4。创建延时任务接口地址:http:yourip:30000apidelaytaskcreate请求类型:POST参数格式:applicationxwwwformurlencoded返回结果:创建成功返回任务id参数列表: 参数名称 参数类型 是否必填 说明 SourceApp string 是 来源 Topic string 是 主题 ContentKey string 是 业务关键字 DelayTimeSpan int 是 延迟相对时间 DelayAbsoluteTime DateTime 是 延迟绝对时间 NotifyUrl string 是 回调地址 NotifyDataType string 是 回调参数格式,仅支持applicationjson和applicationxwwwformurlencoded NotifyBody string 是 回调参数,json格式字符串for(inti0;i5;i){intrndNumnewRandom()。Next(20,500);ListKeyValuePairstring,stringargsnewListKeyValuePairstring,string();args。Add(newKeyValuePairstring,string(SourceApp,TestApp));args。Add(newKeyValuePairstring,string(Topic,TestApp。Trade。TimeoutCancel));args。Add(newKeyValuePairstring,string(ContentKey,i。ToString()));args。Add(newKeyValuePairstring,string(DelayTimeSpan,rndNum。ToString()));args。Add(newKeyValuePairstring,string(DelayAbsoluteTime,DateTime。Now。AddSeconds(rndNum)。ToString(yyyyMMddHH:mm:ss)));args。Add(newKeyValuePairstring,string(NotifyUrl,http:localhost:56655api1。0valuedelaypost));args。Add(newKeyValuePairstring,string(NotifyDataType,applicationjson));args。Add(newKeyValuePairstring,string(NotifyBody,{Posts:〔{PostId:666,Title:tester,Content:testtesttest}〕,BlogId:111,Url:qweqrrttryrtyrtrtrt}));HttpContentreqContentnewFormUrlEncodedContent(args);varresponseawaitclient。PostAsync(http:localhost:30000apiDelayTaskCreate,reqContent);varcontentawaitresponse。Content。ReadAsStringAsync();Debug。WriteLine(content);}4。框架简单分析1。全局设计 根据官网的设计图,以及操作的流程,简单总结一下任务全局流程为客户端masterwork执行任务。从大的架构方向的思想就是,将原有单个服务中业务和任务调度混合的方式做一些改变,使业务和调度分离,专门把任务调度部分剥离出来,作为一个独立的进程,来统一调用和管理任务,而原有服务只做业务处理。 2。Master和Work分析 我们主要从主节点,从节点,数据表这几个方面来简单分析,整个业务的时序流程,从本质来看并不复杂master和Work之间的关系是相互配合的,可能乍一看下面整个图有点混乱,下面来解释一下,其实Master节点将任务添加到数据中,然后work节点,去从对应的数据表中取出任务数据,然后根据任务对应的配置,生成配置信息,调用Quartz执行任务,这就是我们整个框架中最核心的业务。 当然master和work除了主要承载了整个管理系统的UI可视化、后台业务操作、任务执行之外,如果从细节以及实现方式来说主要做了以下事情: Master1。分配任务执行和选择节点2。对work节点进行健康检查,对任务进行故障转移 Work1。取出任务配置信息2。使用Quartz根据配置运行任务3。使用反射调用程序集4。使用httpclient调用http接口 文章来自https:www。cnblogs。comyuxl01p16311534。html