@[toc]

一、ScheduleMaster 外围概念

  • 概念
    对立执多个零碎的工作【回收超时订单,清理垃圾信息 】,如图:

二、ScheduleMaster 利用场景

  • 场景
    次要利用在微服务零碎中。
    如图:

三、ScheduleMaster 我的项目落地

  • 工具

    • ScheduleMaster
      网盘下载地址:
      链接:https://pan.baidu.com/s/1LcCH...
      提取码: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<HomeController> logger;  public HomeController(ILogger<HomeController> _logger) {      logger = _logger;  }   /// <summary>  /// 超时订单回收接口  /// </summary>  /// <returns></returns>  [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接口工作(应用代码自定义创立工作)

  • 实现代码如下:

          /// <summary>      /// 通过代码创立工作      /// </summary>      /// <returns></returns>      [HttpPost("CreateTask")]      public async Task<IActionResult> CreateTask()      {          HttpClient client = new HttpClient();          //登录 设置用户名和明码          client.DefaultRequestHeaders.Add("ms_auth_user", "admin");          client.DefaultRequestHeaders.Add("ms_auth_secret", MD5($"admin{MD5("111111")}admin"));          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", "0/5 * * * * ?"));          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", "order_cancel_http_api"));          args.Add(new KeyValuePair<string, string>("HttpRequestUrl", "http://localhost:5000/Order"));          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();          logger.LogInformation(content);           return Ok("创立胜利");       }       /// <summary>      /// MD5加密      /// </summary>      /// <param name="prestr"></param>      /// <returns></returns>      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<int>监护人id
      NextsList<guid>子级任务id
      ExecutorsList<string>执行节点名称
      RunNowbool创立胜利是否立刻启动
      ParamsList<ScheduleParam>自定义参数列表,也能够通过CustomParamsJson字段间接传json格局字符串

      ScheduleParam:

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

      代码示例:

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

      要提一下的是,应用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<int>监护人id
      NextsList<guid>子级任务id
      ExecutorsList<string>执行节点名称
      RunNowbool创立胜利是否立刻启动

      代码示例:

          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);
    • 创立延时工作

      • 接口地址: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<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);    }

      七、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接口,定时工作一直的检测以后的节点是否可用],会间接转移到其余节点执行工作,运行后果如下: