乐趣区

关于golang:为开源项目-goginapi-增加后台任务模块

工作治理界面 (WEB)

反对在 WEB 界面 中对工作进行治理,例如: 新增工作 编辑工作 启用 / 禁用工作 手动执行工作 等。

工作的属性包含:

  • 工作名称
  • 执行形式

    • SHELL
    • HTTP
  • 表达式(/5 *)
  • 命令
  • 超时工夫(秒)
  • 重试次数
  • 重试距离(秒)
  • 执行完结是否告诉

    • 不告诉
    • 失败告诉
    • 完结告诉
    • 后果关键字匹配告诉
  • 状态
  • 备注

当执行形式为 HTTP 时,反对抉择申请形式 GETPOST

当设置执行完结告诉时,反对抉择告诉形式 邮件 或 Webhook

当设置邮件告诉时,反对输出邮箱地址多个用, 宰割;

当设置后果关键字匹配告诉时,反对输出关键字多个用, 宰割;

工作减少实现后,会把工作数据长久化到 MySQL 中。

任务调度器

参考了两个开源组件:

  • robfig/cron
  • jakecoffman/cron

最终抉择应用 jakecoffman/cron,后者是在前者的根底上做了肯定的补充,例如 AddFunc() 减少了 name 参数,同时还减少了 RemoveJob(name string) 反对删除特定的工作。

// AddFunc adds a func to the Cron to be run on the given schedule.
func (c *Cron) AddFunc(spec string, cmd func(), name string) {c.AddJob(spec, FuncJob(cmd), name)
}

...

// RemoveJob removes a Job from the Cron based on name.
func (c *Cron) RemoveJob(name string) {
    if !c.running {i := c.entries.pos(name)

        if i == -1 {return}

        c.entries = c.entries[:i+copy(c.entries[i:], c.entries[i+1:])]
        return
    }

    c.remove <- name
}

对其简略封装下就能够应用了,上面是封装的办法,办法的具体实现与应用从 go-gin-api 中获取。

type Server interface {i()

    // Start 启动 cron 服务
    Start()

    // Stop 进行 cron 服务
    Stop()

    // AddTask 减少定时工作
    AddTask(task *cron_task_repo.CronTask)

    // RemoveTask 删除定时工作
    RemoveTask(taskId int)

    // AddJob 减少定时工作执行的工作内容
    AddJob(task *cron_task_repo.CronTask) cron.FuncJob
}

当调用 Start() 启动服务时,会把 MySQL 中的工作列表加载到调度器中。

通过以上办法,当从 WEB 界面 操作 新增、编辑、启用 / 禁用、手动执行工作时,能够动静的对调度器中的工作进行治理。

工作执行器

工作执行器指的是工作实在执行所在的机器。

我的思路是应用 Kafka 的公布与订阅性能,当调度器发现须要执行的工作时,将工作信息写到 KafkaTopic 中,工作执行器订阅相干的 Topic 获取工作信息而后执行工作。

如果工作的执行形式为 HTTP,那么工作执行器能够为一组集群,专门解决调用 HTTP 工作,这里能够为一个生产组(Consumer Group),也可适具体场景而定。

如果工作的执行形式为 SHELL,那么工作执行器必须在脚本所在的宿主机上,这里能够为一个具体任务的消费者。

如果任务量过多,能够思考依据业务场景多设置几个 Topic

在我的项目中为了便于演示,不写入到 Kafka 中,仅记录了日志。

func (s *server) AddJob(task *cron_task_repo.CronTask) cron.FuncJob {return func() {s.taskCount.Add()
        defer s.taskCount.Done()

        msg := fmt.Sprintf("开始执行工作:(%d)%s [%s]", task.Id, task.Name, task.Spec)
        s.logger.Info(msg)
    }
}

日志目录:/logs/go-gin-api-cron.log

小结

本文纯属抛砖引玉,有问题,欢送批评指正。

go-gin-api 我的项目安装简单,开箱即用,创立一个后台任务试试吧。

举荐浏览

  • go-gin-api 两个被频繁问的写法问题
  • go-gin-api 新增两个语言包相干性能
退出移动版