ScheduleMaster分布式任务调度中心基本使用和原理

ScheduleMaster分布式任务调度中心基本使用和原理,第1张

文章目录
    • 一、ScheduleMaster 核心概念
    • 二、ScheduleMaster 应用场景
    • 三、ScheduleMaster 项目落地
    • 四、ScheduleMaster 运行原理
    • 五、ScheduleMaster 程序集任务
    • 六、ScheduleMaster API接口任务(使用代码自定义创建任务)
    • 七、ScheduleMaster 集群和集群原理

一、ScheduleMaster 核心概念
  • 概念
    统一执多个系统的任务【回收超时订单,清理垃圾信息 】,如图:
二、ScheduleMaster 应用场景
  • 场景
    主要应用在微服务系统中。
    如图:
三、ScheduleMaster 项目落地
  • 工具
    • ScheduleMaster
      网盘下载地址:
      链接:https://pan.baidu.com/s/1LcCHS__zRRJv_HHwsza3cg
      提取码:eyup
    • Demo 项目
  • 步骤
    • 运行ScheduleMaster

      • 启动命令

        #进入Hos.ScheduleMaster.Web\bin\Release\netcoreapp3.1\publish目录中启动
        #备注:默认数据库为sqlserver,如果其他数据库需要在appsettings.json中修改数据库类型和数据库连接地址
          dotnet Hos.ScheduleMaster.Web.dll
        #进入Hos.ScheduleMaster.QuartzHost\bin\Release\netcoreapp3.1\publish 目录中启动
          dotnet Hos.ScheduleMaster.QuartzHost.dll --urls http://*:30001
        

        运行结果如图:

        浏览器运行结果:http://localhost:30000,用户名:admin 密码:111111
        如图:

    • Demo项目

      • 新建一个订单回收API接口
          private readonly ILogger logger;
          public HomeController(ILogger _logger) {
              logger = _logger;
          } 
          /// 
          /// 超时订单回收接口
          /// 
          /// 
          [HttpPost]
          public IActionResult OrderCancel() 
          {
              logger.LogInformation("回收订单任务");
              return Ok("回收订单任务");
          }
        
    • 新建任务

      • 点击任务列表
        如图:

      • 点击创建任务按钮->选择 “基础信息配置”
        如图:


        选择“元数据配置”,在点击“保存”即可,如图:

      • 运行结果(每隔5秒进行调用订单回收接口),如图:

四、ScheduleMaster 运行原理
  • 原理
    • Master 概念
      主节点:协调 Hos.ScheduleMaster.Web

    • Node 概念
      工作节点:执行业务 Hos.ScheduleMaster.QuartzHost

    • 数据库
      用来存储任务信息。

    • 全局架构
      如图:

    • 执行过程
      客户端---->Hos.ScheduleMaster.Web(master节点)---->Hos.ScheduleMaster.QuartzHost(工作节点)---->订单回收接口

      • master节点的核心
        • 选择工作节点
        • 指定工作节点,执行任务
      • 工作节点的核心
        • 取出任务配置信息
        • 使用Quartz根据配置运行任务
          • 使用HttpClient 调用接口
          • 使用反射调用程序集方法
五、ScheduleMaster 程序集任务
  • 工具
    • 控制台Demo项目
    • ScheduleMaster
  • 步骤
    • 新建一个Console项目

        //项目安装  
        ScheduleMaster
      

      新建OrderServer类继承

         public  class OrderServer:TaskBase
         {  
           public override void Run(TaskContext context)
           {
              //超时订单逻辑
              context.WriteLog("订单开始回收.......成功");
           }
         }
      
      • 控制台项目打包
        项目编译后,进入 bin文件件,将Hos.ScheduleMaster.Base.dll除外的所有的文件打包成压缩文件,如图:
    • ScheduleMaster 配置

      • 点击“任务列表”目录,点击“创建任务”按钮,任务类型选择“程序集任务”,如图:
六、ScheduleMaster API接口任务(使用代码自定义创建任务)
  • 实现代码如下:

          /// 
          /// 通过代码创建任务
          /// 
          /// 
          [HttpPost("CreateTask")]
          public async Task CreateTask()
          {
              HttpClient client = new HttpClient();
              //登录 设置用户名和密码
              client.DefaultRequestHeaders.Add("ms_auth_user", "admin");
              client.DefaultRequestHeaders.Add("ms_auth_secret", MD5($"admin{MD5("111111")}admin"));
              List> args = new List>();
              args.Add(new KeyValuePair("MetaType", "2"));
              args.Add(new KeyValuePair("RunLoop", "true"));
              args.Add(new KeyValuePair("CronExpression", "0/5 * * * * ?"));
              args.Add(new KeyValuePair("Remark", "By Xunit Tester Created"));
              args.Add(new KeyValuePair("StartDate", DateTime.Today.ToString("yyyy-MM-dd HH:mm:ss")));
              args.Add(new KeyValuePair("Title", "order_cancel_http_api"));
              args.Add(new KeyValuePair("HttpRequestUrl", "http://localhost:5000/Order"));
              args.Add(new KeyValuePair("HttpMethod", "POST"));
              args.Add(new KeyValuePair("HttpContentType", "application/json"));
              args.Add(new KeyValuePair("HttpHeaders", "[]"));
              args.Add(new KeyValuePair("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();
              logger.LogInformation(content); 
              return Ok("创建成功"); 
          } 
          /// 
          /// MD5加密
          /// 
          /// 
          /// 
          public static string MD5(string prestr)
          {
              StringBuilder sb = new StringBuilder(32);
              MD5 md5 = new MD5CryptoServiceProvider();
              byte[] t = md5.ComputeHash(Encoding.GetEncoding("UTF-8").GetBytes(prestr));
              for (int i = 0; i < t.Length; i++)
              {
                  sb.Append(t[i].ToString("x").PadLeft(2, '0'));
              }
              return sb.ToString();
          } 
    
  • 官方API

    • 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"));
      

    签名验证这块设计的比较简单,具体源码逻辑可以参考Hos.ScheduleMaster.Web.Filters.AccessControlFilter

    • API返回格式
      所有接口采用统一的返回格式,字段如下:

      参数名称参数类型说明
      Successbool是否成功
      Statusint结果状态,0-请求失败 1-请求成功 2-登录失败 3-参数异常 4-数据异常
      Messagestring返回的消息
      Dataobject返回的数据
    • 创建程序集任务

      • 接口地址:http://yourip:30000/api/task/create
      • 请求类型:POST
      • 参数格式:application/x-www-form-urlencoded
      • 返回结果:创建成功返回任务id
      • 参数列表:
      参数名称参数类型是否必填说明
      MetaTypeint任务类型,这里固定是1
      Titlestring任务名称
      RunLoopbool是否按周期执行
      CronExpressionstringcron表达式,如果RunLoop为true则必填
      AssemblyNamestring程序集名称
      ClassNamestring执行类名称,包含完整命名空间
      StartDateDateTime任务开始时间
      EndDateDateTime任务停止时间,为空表示不限停止时间
      Remarkstring任务描述说明
      KeepersList监护人id
      NextsList子级任务id
      ExecutorsList执行节点名称
      RunNowbool创建成功是否立即启动
      ParamsList自定义参数列表,也可以通过CustomParamsJson字段直接传json格式字符串

      ScheduleParam:

      参数名称参数类型是否必填说明
      ParamKeystring参数名称
      ParamValuestring参数值
      ParamRemarkstring参数说明

      代码示例:

          HttpClient client = new HttpClient();
          List> args = new List>();
          args.Add(new KeyValuePair("MetaType", "1"));
          args.Add(new KeyValuePair("RunLoop", "true"));
          args.Add(new KeyValuePair("CronExpression", "33 0/8 * * * ?"));
          args.Add(new KeyValuePair("Remark", "By Xunit Tester Created"));
          args.Add(new KeyValuePair("StartDate", DateTime.Today.ToString("yyyy-MM-dd HH:mm:ss")));
          args.Add(new KeyValuePair("Title", "程序集接口测试任务"));
          args.Add(new KeyValuePair("AssemblyName", "Hos.ScheduleMaster.Demo"));
          args.Add(new KeyValuePair("ClassName", "Hos.ScheduleMaster.Demo.Simple"));
          args.Add(new KeyValuePair("CustomParamsJson", "[{\"ParamKey\":\"k1\",\"ParamValue\":\"1111\",\"ParamRemark\":\"r1\"},{\"ParamKey\":\"k2\",\"ParamValue\":\"2222\",\"ParamRemark\":\"r2\"}]"));
          args.Add(new KeyValuePair("Keepers", "1"));
          args.Add(new KeyValuePair("Keepers", "2"));
          //args.Add(new KeyValuePair("Nexts", ""));
          //args.Add(new KeyValuePair("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);
      

      要提一下的是,使用API创建任务的方式不支持上传程序包,所以在任务需要启动时要确保程序包已通过其他方式上传,否则会启动失败。

    • 创建HTTP任务

      • 接口地址:http://yourip:30000/api/task/create
      • 请求类型:POST
      • 参数格式:application/x-www-form-urlencoded
      • 返回结果:创建成功返回任务id
      • 参数列表:
      参数名称参数类型是否必填说明
      MetaTypeint任务类型,这里固定是2
      Titlestring任务名称
      RunLoopbool是否按周期执行
      CronExpressionstringcron表达式,如果RunLoop为true则必填
      StartDateDateTime任务开始时间
      EndDateDateTime任务停止时间,为空表示不限停止时间
      Remarkstring任务描述说明
      HttpRequestUrlstring请求地址
      HttpMethodstring请求方式,仅支持GET\POST\PUT\DELETE
      HttpContentTypestring参数格式,仅支持application/json和application/x-www-form-urlencoded
      HttpHeadersstring自定义请求头,ScheduleParam列表的json字符串
      HttpBodystring如果是json格式参数,则是对应参数的json字符串;如果是form格式参数,则是对应ScheduleParam列表的json字符串。
      KeepersList监护人id
      NextsList子级任务id
      ExecutorsList执行节点名称
      RunNowbool创建成功是否立即启动

      代码示例:

          HttpClient client = new HttpClient();
          List> args = new List>();
          args.Add(new KeyValuePair("MetaType", "2"));
          args.Add(new KeyValuePair("RunLoop", "true"));
          args.Add(new KeyValuePair("CronExpression", "22 0/8 * * * ?"));
          args.Add(new KeyValuePair("Remark", "By Xunit Tester Created"));
          args.Add(new KeyValuePair("StartDate", DateTime.Today.ToString("yyyy-MM-dd HH:mm:ss")));
          args.Add(new KeyValuePair("Title", "Http接口测试任务"));
          args.Add(new KeyValuePair("HttpRequestUrl", "http://localhost:56655/api/1.0/value/jsonpost"));
          args.Add(new KeyValuePair("HttpMethod", "POST"));
          args.Add(new KeyValuePair("HttpContentType", "application/json"));
          args.Add(new KeyValuePair("HttpHeaders", "[]"));
          args.Add(new KeyValuePair("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);
      
    • 创建延时任务

      • 接口地址: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-urlencoded
      NotifyBodystring回调参数,json格式字符串

      代码示例:

          for (int i = 0; i < 5; i++)
          {
              int rndNum = new Random().Next(20, 500);
              List> args = new List>();
              args.Add(new KeyValuePair("SourceApp", "TestApp"));
              args.Add(new KeyValuePair("Topic", "TestApp.Trade.TimeoutCancel"));
              args.Add(new KeyValuePair("ContentKey", i.ToString()));
              args.Add(new KeyValuePair("DelayTimeSpan", rndNum.ToString()));
              args.Add(new KeyValuePair("DelayAbsoluteTime", DateTime.Now.AddSeconds(rndNum).ToString("yyyy-MM-dd HH:mm:ss")));
              args.Add(new KeyValuePair("NotifyUrl", "http://localhost:56655/api/1.0/value/delaypost"));
              args.Add(new KeyValuePair("NotifyDataType", "application/json"));
              args.Add(new KeyValuePair("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);
          }
      
七、ScheduleMaster 集群和集群原理
  • 主要针对工作节点使用集群

    • 步骤
      • 进入工作节点项目根目录下【ScheduleMasterCore\Hos.ScheduleMaster.QuartzHost\bin\Release\netcoreapp3.1\publish】,更改配置文件【appsettings.json】, 因为要启动多个节点,只需要更改节点名称和端口号即可【切记:节点名称不能够重复】,如下:
          "NodeSetting": {
            "IdentityName": "worker1",  //节点名称
            "Role": "worker",
            "Protocol": "http",
            "IP": "localhost",
            "Port": 30001,  //端口号
            "Priority": 1,
            "MaxConcurrency": 20
          }
        
      • 启动
          #进入Hos.ScheduleMaster.QuartzHost\bin\Release\netcoreapp3.1\publish 目录中启动
          dotnet Hos.ScheduleMaster.QuartzHost.dll --urls http://*:30002
        
      • 运行结果,如图:
  • 场景

    • 如果当前的工作节点宕机了,会不会转移到其他的工作节点上?
      需要更改任务的执行节点,选择多个执行节点,如图:

      有两个工作节点,30001和30002,其中把30001宕机了[有个心跳检测的API接口,定时任务不断的检测当前的节点是否可用],会直接转移到其他节点执行任务,运行结果如下:

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/728059.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-26
下一篇 2022-04-26

发表评论

登录后才能评论

评论列表(0条)

保存