.NET Core 分布式任务调度ScheduleMaster详解
1.什么是ScheduleMaster
ScheduleMaster是分布式任务调度
系统,是国内的一位开发者写的。简称:集中任务调度系统,最简单的理解ScheduleMaster,就是对不同的系统里面的调度任务做统一管理的框架。
例如我们现在有多个系统,每个系统针对自己处理不同的业务场景。衍生出自己的调度任务,想象一下,如果每个系统人为去维护,那随着调度任务越来越多,人是崩溃的吧,可见维护和技术成本是巨大的,这时我们需要选择分布式任务系统框架做统一的管理
当然有目前有很多相对优秀分布式任务系统框架,我们主要学习 ScheduleMaster
2.使用ScheduleMaster
1.首先我们需要使用NET Core web Api创建几个模拟的微服务,分别为 考勤、算薪、邮件、短信
2.下载开源的ScheduleMaster,并且使用ScheduleMaster调度我们的微服务接口
- sqlserver:"Persist Security Info = False; User ID =sa; Password =123456; Initial Catalog =schedule_master; Server =."
- postgresql:"Server=localhost;Port=5432;Database=schedule_master;User Id=postgres;Password=123456;Pooling=true;MaxPoolSize=20;"
- mysql:"Data Source=localhost;Database=schedule_master;User ID=root;Password=123456;pooling=true;CharSet=utf8mb4;port=3306;sslmode=none;TreatTinyAsBoolean=true"
修改Host的配置文件和支持的数据库,框架默认使用Mysql
修改Web的配置文件和支持的数据库,框架默认使用Mysql
3.进入Hos.ScheduleMaster.Web项目的发布目录,dotnet Hos.ScheduleMaster.Web.dll
启动项目 ,此时会生成数据库
登录账号:admin
密码:111111
4.进入Hos.ScheduleMaster.QuartzHost项目的发布目录,执行命令,启动项目
dotnet Hos.ScheduleMaster.QuartzHost.dll --urls http://*:30003
1.配置Http调度任务
5.准备就绪后,使用后台查看节点管理,可以看到web主节点30000和任务调度的接口30002已经在运行
6.使用任务列表菜单,创建定时调度任务,配置基础信息和元数据配置,然后点击保存就开始执行任务
2.配置程序集调度任务
1.创建一个类库,安装ScheduleMaster库, 创建一个类继承TaskBase,实现抽象方法,然后编译程序集
namespace TaskExcuteService { class AssemblyTask : TaskBase { public override void Run(TaskContext context) { context.WriteLog("程序集任务"); } } }
2.找到debug目录,去掉Base程序集,然后添加为压缩文件
3.在web界面找到任务配置,选择程序集进行基本配置,配置元数据,输入程序集名称,然后输入类,并将程序集上传,保存就可以运行了
3.使用Api接入任务
为了方便业务系统更好的接入调度系统,ScheduleMaster创建任务不仅可以在控制台中实现,系统也提供了WebAPI供业务系统使用代码接入,这种方式对延时任务来说尤其重要。
1.API Server 对接流程
- 在控制台中创建好专用的API对接用户账号。
- 使用对接账号的用户名设置为http header中的
ms_auth_user
值。 - 使用经过哈希运算过的秘钥设置为http header中的
ms_auth_secret值
,计算规则:按{用户名}{hash(密码)}{用户名}的格式拼接得到字符串str,然后再对str做一次hash运算即得到最终秘钥,hash函数是小写的32位MD5算法。 - 使用form格式发起http调用,如果非法用户会返回401-Unauthorized。
HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Add("ms_auth_user", "admin"); client.DefaultRequestHeaders.Add("ms_auth_secret", SecurityHelper.MD5($"admin{SecurityHelper.MD5("111111")}}admin"));
所有接口采用统一的返回格式,字段如下:
参数名称 | 参数类型 | 说明 |
---|---|---|
Success | bool | 是否成功 |
Status | int | 结果状态,0-请求失败 1-请求成功 2-登录失败 3-参数异常 4-数据异常 |
Message | string | 返回的消息 |
Data | object | 返回的数据 |
2.创建程序集任务
使用API创建任务的方式不支持上传程序包,所以在任务需要启动时要确保程序包已通过其他方式上传,否则会启动失败。
- 接口地址:
http://yourip:30000/api/task/create
- 请求类型:
POST
- 参数格式:
application/x-www-form-urlencoded
- 返回结果:创建成功返回任务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<int> | 否 | 监护人id |
Nexts | List<guid> | 否 | 子级任务id |
Executors | List<string> | 否 | 执行节点名称 |
RunNow | bool | 否 | 创建成功是否立即启动 |
Params | List<ScheduleParam> | 否 | 自定义参数列表,也可以通过CustomParamsJson字段直接传json格式字符串 |
ScheduleParam:
参数名称 | 参数类型 | 是否必填 | 说明 |
---|---|---|---|
ParamKey | string | 是 | 参数名称 |
ParamValue | string | 是 | 参数值 |
ParamRemark | string | 否 | 参数说明 |
HttpClient client = new HttpClient(); List<KeyValuePair<string, string>> args = new List<KeyValuePair<string, string>>(); args.Add(new KeyValuePair<string, string>("MetaType", "1")); args.Add(new KeyValuePair<string, string>("RunLoop", "true")); args.Add(new KeyValuePair<string, string>("CronExpression", "33 0/8 * * * ?")); args.Add(new KeyValuePair<string, string>("Remark", "By Xunit Tester Created")); args.Add(new KeyValuePair<string, string>("StartDate", DateTime.Today.ToString("yyyy-MM-dd HH:mm:ss"))); args.Add(new KeyValuePair<string, string>("Title", "程序集接口测试任务")); args.Add(new KeyValuePair<string, string>("AssemblyName", "Hos.ScheduleMaster.Demo")); args.Add(new KeyValuePair<string, string>("ClassName", "Hos.ScheduleMaster.Demo.Simple")); args.Add(new KeyValuePair<string, string>("CustomParamsJson", "[{\"ParamKey\":\"k1\",\"ParamValue\":\"1111\",\"ParamRemark\":\"r1\"},{\"ParamKey\":\"k2\",\"ParamValue\":\"2222\",\"ParamRemark\":\"r2\"}]")); args.Add(new KeyValuePair<string, string>("Keepers", "1")); args.Add(new KeyValuePair<string, string>("Keepers", "2")); //args.Add(new KeyValuePair<string, string>("Nexts", "")); //args.Add(new KeyValuePair<string, string>("Executors", "")); HttpContent reqContent = new FormUrlEncodedContent(args); var response = await client.PostAsync("http://localhost:30000/api/Task/Create", reqContent); var content = await response.Content.ReadAsStringAsync(); Debug.WriteLine(content);
3.创建HTTP任务
- 接口地址:
http://yourip:30000/api/task/create
- 请求类型:
POST
- 参数格式:
application/x-www-form-urlencoded
- 返回结果:创建成功返回任务id
- 参数列表:
参数名称 | 参数类型 | 是否必填 | 说明 |
---|---|---|---|
MetaType | int | 是 | 任务类型,这里固定是2 |
Title | string | 是 | 任务名称 |
RunLoop | bool | 是 | 是否按周期执行 |
CronExpression | string | 否 | cron表达式,如果RunLoop为true则必填 |
StartDate | DateTime | 是 | 任务开始时间 |
EndDate | DateTime | 否 | 任务停止时间,为空表示不限停止时间 |
Remark | string | 否 | 任务描述说明 |
HttpRequestUrl | string | 是 | 请求地址 |
HttpMethod | string | 是 | 请求方式,仅支持GET\POST\PUT\DELETE |
HttpContentType | string | 是 | 参数格式,仅支持application/json和application/x-www-form-urlencoded |
HttpHeaders | string | 否 | 自定义请求头,ScheduleParam列表的json字符串 |
HttpBody | string | 是 | 如果是json格式参数,则是对应参数的json字符串;如果是form格式参数,则是对应ScheduleParam列表的json字符串。 |
Keepers | List<int> | 否 | 监护人id |
Nexts | List<guid> | 否 | 子级任务id |
Executors | List<string> | 否 | 执行节点名称 |
RunNow | bool | 否 | 创建成功是否立即启动 |
HttpClient client = new HttpClient(); List<KeyValuePair<string, string>> args = new List<KeyValuePair<string, string>>(); args.Add(new KeyValuePair<string, string>("MetaType", "2")); args.Add(new KeyValuePair<string, string>("RunLoop", "true")); args.Add(new KeyValuePair<string, string>("CronExpression", "22 0/8 * * * ?")); args.Add(new KeyValuePair<string, string>("Remark", "By Xunit Tester Created")); args.Add(new KeyValuePair<string, string>("StartDate", DateTime.Today.ToString("yyyy-MM-dd HH:mm:ss"))); args.Add(new KeyValuePair<string, string>("Title", "Http接口测试任务")); args.Add(new KeyValuePair<string, string>("HttpRequestUrl", "http://localhost:56655/api/1.0/value/jsonpost")); args.Add(new KeyValuePair<string, string>("HttpMethod", "POST")); args.Add(new KeyValuePair<string, string>("HttpContentType", "application/json")); args.Add(new KeyValuePair<string, string>("HttpHeaders", "[]")); args.Add(new KeyValuePair<string, string>("HttpBody", "{ \"Posts\": [{ \"PostId\": 666, \"Title\": \"tester\", \"Content\":\"testtesttest\" }], \"BlogId\": 111, \"Url\":\"qweqrrttryrtyrtrtrt\" }")); HttpContent reqContent = new FormUrlEncodedContent(args); var response = await client.PostAsync("http://localhost:30000/api/Task/Create", reqContent); var content = await response.Content.ReadAsStringAsync(); Debug.WriteLine(content);
4.创建延时任务
- 接口地址:
http://yourip:30000/api/delaytask/create
- 请求类型:
POST
- 参数格式:
application/x-www-form-urlencoded
- 返回结果:创建成功返回任务id
- 参数列表:
参数名称 | 参数类型 | 是否必填 | 说明 |
---|---|---|---|
SourceApp | string | 是 | 来源 |
Topic | string | 是 | 主题 |
ContentKey | string | 是 | 业务关键字 |
DelayTimeSpan | int | 是 | 延迟相对时间 |
DelayAbsoluteTime | DateTime | 是 | 延迟绝对时间 |
NotifyUrl | string | 是 | 回调地址 |
NotifyDataType | string | 是 | 回调参数格式,仅支持application/json和application/x-www-form-urlencoded |
NotifyBody | string | 是 | 回调参数,json格式字符串 |
for (int i = 0; i < 5; i++) { int rndNum = new Random().Next(20, 500); List<KeyValuePair<string, string>> args = new List<KeyValuePair<string, string>>(); args.Add(new KeyValuePair<string, string>("SourceApp", "TestApp")); args.Add(new KeyValuePair<string, string>("Topic", "TestApp.Trade.TimeoutCancel")); args.Add(new KeyValuePair<string, string>("ContentKey", i.ToString())); args.Add(new KeyValuePair<string, string>("DelayTimeSpan", rndNum.ToString())); args.Add(new KeyValuePair<string, string>("DelayAbsoluteTime", DateTime.Now.AddSeconds(rndNum).ToString("yyyy-MM-dd HH:mm:ss"))); args.Add(new KeyValuePair<string, string>("NotifyUrl", "http://localhost:56655/api/1.0/value/delaypost")); args.Add(new KeyValuePair<string, string>("NotifyDataType", "application/json")); args.Add(new KeyValuePair<string, string>("NotifyBody", "{ \"Posts\": [{ \"PostId\": 666, \"Title\": \"tester\", \"Content\":\"testtesttest\" }], \"BlogId\": 111, \"Url\":\"qweqrrttryrtyrtrtrt\" }")); HttpContent reqContent = new FormUrlEncodedContent(args); var response = await client.PostAsync("http://localhost:30000/api/DelayTask/Create", reqContent); var content = await response.Content.ReadAsStringAsync(); Debug.WriteLine(content); }
4.框架简单分析
1.全局设计
根据官网的设计图,以及操作的流程,简单总结一下任务全局流程为客户端—–>master——>work—–>执行任务。从大的架构方向的思想就是,将原有单个服务中业务和任务调度混合的方式做一些改变,使业务和调度分离,专门把任务调度部分剥离出来,作为一个独立的进程,来统一调用和管理任务,而原有服务只做业务处理。
2.Master和Work分析
我们主要从主节点,从节点,数据表这几个方面来简单分析,整个业务的时序流程,从本质来看并不复杂master和Work之间的关系是相互配合的,可能乍一看下面整个图有点混乱,下面来解释一下,其实Master节点将任务添加到数据中,然后work节点,去从对应的数据表中取出任务数据,然后根据任务对应的配置,生成配置信息,调用Quartz执行任务,这就是我们整个框架中最核心的业务。
当然master和work除了主要承载了整个管理系统的UI可视化、后台业务操作、任务执行之外,如果从细节以及实现方式来说主要做了以下事情:
Master
- 1.分配任务执行和选择节点
- 2.对work节点进行健康检查,对任务进行故障转移
Work
- 1.取出任务配置信息
- 2.使用Quartz根据配置运行任务
- 3.使用反射调用程序集
- 4.使用httpclient调用http 接口
到此这篇关于分布式任务调度ScheduleMaster的文章就介绍到这了,更多相关分布式任务调度ScheduleMaster内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
原文出处:https://www.cnblogs.com/yuxl01/p/16311534.html
相关文章
- Ray是一种分布式执行框架,便于大规模应用程序和利用先进的机器学习库,今天给大家分享支持python的分布式计算框架Ray详解,感兴趣的朋友一起看看吧...2021-07-29
详解GaussDB(DWS) explain分布式执行计划的示例
这篇文章主要介绍了详解GaussDB(DWS) explain分布式执行计划,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-12-08- 这篇文章主要详细介绍了C++实现的分布式游戏服务端引擎KBEngine的概念以及使用方法,非常的实用,有需要的小伙伴可以参考下...2020-04-25
- 这篇文章主要介绍了分布式文档存储数据库之MongoDB备份与恢复,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-12-08
分布式监控系统之Zabbix 使用SNMP、JMX信道采集数据的原理解析
这篇文章主要介绍了分布式监控系统之Zabbix 使用SNMP、JMX信道采集数据,本文给大家介绍的非常详细,对大家的学习或工作就有一定的参考借鉴价值,需要的朋友可以参考下...2021-05-07- 提到分布式算法,就不得不提 Paxos 算法,在过去几十年里,它基本上是分布式共识的代 名词,因为当前最常用的一批共识算法都是基于它改进的。比如,Fast Paxos 算法、 Cheap Paxos 算法、Raft 算法、ZAB 协议等等。...2021-05-19
- 在分布式系统、微服务架构大行其道的今天,服务间互相调用出现失败已经成为常态,本文侧重于其他几项,关于 2PC、3PC 传统事务,网上资料已经非常多了,这里不多做重复,本文通过示例给大家介绍Java分布式事务的 6 种解决方案,一起看看吧...2021-06-26
- 这篇文章主要介绍了分布式文档存储数据库之MongoDB访问控制的操作方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-12-08
- 这篇文章主要介绍了详解三分钟快速搭建分布式高可用的Redis集群,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-05
docker compose 一键部署分布式配置中心Apollo的过程详解
这篇文章主要介绍了docker compose 一键部署分布式配置中心Apollo,今天我们使用Docker来进行搭建,毕竟Docker对于开发者来说更友好一些,需要的朋友可以参考下...2021-09-19- 我们将会谈到的是ASP.NET通过分布式Session来构建高性能可扩展的ASP.NET网站...2021-09-22
springboot cloud使用eureka整合分布式事务组件Seata 的方法
这篇文章主要介绍了springboot cloud使用eureka整合分布式事务组件Seata 的方法 ,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-05-02- 这篇文章主要介绍了MongoDB 分布式集群的相关资料,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-12-08
- 这篇文章主要介绍了基于python分布式爬虫并解决假死的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-15
分布式监控系统之Zabbix主动、被动及web监控的过程详解
这篇文章主要介绍了分布式监控系统之Zabbix主动、被动及web监控的过程详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-05-07- 本文给大家分享.net core 使用阿里云分布式日志的实现代码,简单查询阿里云日志的工具使用,通过实例代码介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-22
- 这篇文章主要介绍了关于注解式的分布式Elasticsearch的封装案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-26
- 这篇文章主要给大家介绍了关于ASP.NET Core利用Jaeger实现分布式追踪的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用ASP.NET Core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2021-09-22
- 这篇文章主要介绍了分布式锁三种实现方式及对比,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2021-01-15
- 这篇文章主要介绍了C#分布式事务的超时处理,以实例形式较为详细的分析了C#分布式事务的超时处理相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25