📣读完这篇文章里你能收获到
- 了解分布式调度中心的概念
- 博主重新整理的ScheduleMaster系统架构图
- 快速接入ScheduleMaster高可用
- 通过WebAPI接入ScheduleMaster
- 感谢点赞+收藏,避免下次找不到~
文章目录
一、ScheduleMaster介绍
1 分布式调度中心的概念
ScheduleMaster是分布式任务调度中心。最简单的理ScheduleMaster,就是对不同的系统里面的调度任务做统一管理的框架。
2 核心功能点
- 简易的Web UI操作;
- 任务动态管理:创建、启动、停止、暂停、恢复、删除等;
- 高可用支持,跨平台多节点部署;
- 数据安全性,不会出现多实例并发调度;
- 支持自定义参数设置;
- 支持设置监护人,运行异常时邮件告警;
- 支持设置任务依赖,自动触发,共享任务结果;
- 插件式开发,任务运行环境隔离;
- 全链路日志系统,运行轨迹轻松掌控;
- 用户访问控制;
- 提供开放REST API,业务系统可以无缝集成;
- 调度报表统计;
3 主要的技术点
- Asp.Net Core 3.0、EntityFramework Core 3.0、Mysql 5.7、Quartz.Net、BeyondAdmin、Jquery
按这个项目开源作者
HOHO
的原话讲就是:没有涉及任何高大上的技术,尽显(低调奢华有内涵)朴实
4 系统架构图
- 我基于其开源的框架图,自己重新梳理了它的架构图
二、项目运行使用
需要提前准备:isual Studio 2019、.NET Core3.1 SDK、Mysql 5.7(可选)、SQLServer(可选)、PostgreSQL(可选)、Centos(可选)、Docker(可选)。
1 下载源码到本地
- 地址:https://github.com/hey-hoho/ScheduleMasterCore
- 然后用VS2019打开解决方案并编译通过
2 修改appsettings.json文件
- 打开项目Hos.ScheduleMaster.Web根目录下的appsettings.json文件,修改数据库连接字符串,再找到NodeSetting节点,修改IP字段为master将要部署的ip地址(master端口为30000不用修改)
- 打开项目Hos.ScheduleMaster.QuartzHost根目录下的appsettings.json文件,同样先修改Mysql连接字符串,再找到NodeSetting节点,设置worker的名称IdentityName,修改IP字段为将要部署的ip地址,Port字段为要监听的地址
3 发布项目
- 在项目Hos.ScheduleMaster.Web、Hos.ScheduleMaster.QuartzHost上右击选择发布…,发布到本地文件夹。
- 新增worker:按同样方式在项目
Hos.ScheduleMaster.QuartzHost
,配置IdentityName、IP、Port即可,worker在启动后会把自己的信息注入到数据库中,在master中可以看到。
- 快速发布小贴士:windows平台下用powershell执行脚本publish.ps1快速发布到d:/sm-publish目录,linux平台下执行脚本sh publish.sh快速发布到/home/sm-publish目录。
4 运行2个worker节点为例
- master节点:找到master的发布目录,执行命令dotnet Hos.ScheduleMaster.Web.dll启动程序,首次启动会自动迁移生成数据库结构并初始化种子数据,打开浏览器输入ip和端口访问即可
初始用户名
admin
,密码
111111
- worker1节点:找到worker的发布目录,执行命令dotnet Hos.ScheduleMaster.QuartzHost.dll --urls http://*:30001启动程序,打开浏览器输入ip和端口会看到一个欢迎页面,表示worker已启动成功。
- worker2节点:修改worker下的appsettings.json文件为worker2的配置(如果发布前已经修改可跳过),执行命令dotnet Hos.ScheduleMaster.QuartzHost.dll --urls http://*:30002启动程序.
三、实际操作
1 后台新建HTTP定时任务
2 API自定义任务
为了方便业务系统更好的接入调度系统,创建任务不仅可以在控制台中实现,系统也提供了WebAPI供业务系统使用代码接入,这种方式对延时任务来说尤其重要。
- 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 =newHttpClient();
client.DefaultRequestHeaders.Add("ms_auth_user","admin");
client.DefaultRequestHeaders.Add("ms_auth_secret", SecurityHelper.MD5($"admin{SecurityHelper.MD5("111111")}}admin"));
签名验证这块设计的比较简单,具体源码逻辑可以参考
Hos.ScheduleMaster.Web.Filters.AccessControlFilter
。
- API返回格式
所有接口采用统一的返回格式,字段如下:
参数名称参数类型说明Successbool是否成功Statusint结果状态,0-请求失败 1-请求成功 2-登录失败 3-参数异常 4-数据异常Messagestring返回的消息Dataobject返回的数据
- 创建HTTP任务
示例:
- 接口地址:
http://yourip:30000/api/task/create
- 请求类型:
POST
- 参数格式:
application/x-www-form-urlencoded
- 返回结果:创建成功返回任务id
- 参数列表:
参数名称参数类型是否必填说明MetaTypeint是任务类型,这里固定是2Titlestring是任务名称RunLoopbool是是否按周期执行CronExpressionstring否cron表达式,如果RunLoop为true则必填StartDateDateTime是任务开始时间EndDateDateTime否任务停止时间,为空表示不限停止时间Remarkstring否任务描述说明HttpRequestUrlstring是请求地址HttpMethodstring是请求方式,仅支持GET\POST\PUT\DELETEHttpContentTypestring是参数格式,仅支持application/json和application/x-www-form-urlencodedHttpHeadersstring否自定义请求头,ScheduleParam列表的json字符串HttpBodystring是如果是json格式参数,则是对应参数的json字符串;如果是form格式参数,则是对应ScheduleParam列表的json字符串。KeepersList<int>否监护人idNextsList<guid>否子级任务idExecutorsList<string>否执行节点名称RunNowbool否创建成功是否立即启动
代码示例:
HttpClient client =newHttpClient();List<KeyValuePair<string,string>> args =newList<KeyValuePair<string,string>>();
args.Add(newKeyValuePair<string,string>("MetaType","2"));
args.Add(newKeyValuePair<string,string>("RunLoop","true"));
args.Add(newKeyValuePair<string,string>("CronExpression","22 0/8 * * * ?"));
args.Add(newKeyValuePair<string,string>("Remark","By Xunit Tester Created"));
args.Add(newKeyValuePair<string,string>("StartDate", DateTime.Today.ToString("yyyy-MM-dd HH:mm:ss")));
args.Add(newKeyValuePair<string,string>("Title","Http接口测试任务"));
args.Add(newKeyValuePair<string,string>("HttpRequestUrl","http://localhost:56655/api/1.0/value/jsonpost"));
args.Add(newKeyValuePair<string,string>("HttpMethod","POST"));
args.Add(newKeyValuePair<string,string>("HttpContentType","application/json"));
args.Add(newKeyValuePair<string,string>("HttpHeaders","[]"));
args.Add(newKeyValuePair<string,string>("HttpBody","{ \"Posts\": [{ \"PostId\": 666, \"Title\": \"tester\", \"Content\":\"testtesttest\" }], \"BlogId\": 111, \"Url\":\"qweqrrttryrtyrtrtrt\" }"));HttpContent reqContent =newFormUrlEncodedContent(args);var response =await client.PostAsync("http://localhost:30000/api/Task/Create", reqContent);var content =await response.Content.ReadAsStringAsync();
Debug.WriteLine(content);
- 创建延时任务
示例:
- 接口地址:
http://yourip:30000/api/delaytask/create
- 请求类型:
POST
- 参数格式:
application/x-www-form-urlencoded
- 返回结果:创建成功返回任务id
- 参数列表:
参数名称参数类型是否必填说明SourceAppstring是来源Topicstring是主题ContentKeystring是业务关键字DelayTimeSpanint是延迟相对时间DelayAbsoluteTimeDateTime是延迟绝对时间NotifyUrlstring是回调地址NotifyDataTypestring是回调参数格式,仅支持application/json和application/x-www-form-urlencodedNotifyBodystring是回调参数,json格式字符串
代码示例:
for(int i =0; i <5; i++){int rndNum =newRandom().Next(20,500);List<KeyValuePair<string,string>> args =newList<KeyValuePair<string,string>>();
args.Add(newKeyValuePair<string,string>("SourceApp","TestApp"));
args.Add(newKeyValuePair<string,string>("Topic","TestApp.Trade.TimeoutCancel"));
args.Add(newKeyValuePair<string,string>("ContentKey", i.ToString()));
args.Add(newKeyValuePair<string,string>("DelayTimeSpan", rndNum.ToString()));
args.Add(newKeyValuePair<string,string>("DelayAbsoluteTime", DateTime.Now.AddSeconds(rndNum).ToString("yyyy-MM-dd HH:mm:ss")));
args.Add(newKeyValuePair<string,string>("NotifyUrl","http://localhost:56655/api/1.0/value/delaypost"));
args.Add(newKeyValuePair<string,string>("NotifyDataType","application/json"));
args.Add(newKeyValuePair<string,string>("NotifyBody","{ \"Posts\": [{ \"PostId\": 666, \"Title\": \"tester\", \"Content\":\"testtesttest\" }], \"BlogId\": 111, \"Url\":\"qweqrrttryrtyrtrtrt\" }"));HttpContent reqContent =newFormUrlEncodedContent(args);var response =await client.PostAsync("http://localhost:30000/api/DelayTask/Create", reqContent);var content =await response.Content.ReadAsStringAsync();
Debug.WriteLine(content);}
版权归原作者 广海_小疯疯丶 所有, 如有侵权,请联系我们删除。