下面我将详细讲解“利用Go语言快速实现一个极简任务调度系统” 的完整攻略。
1. 前言
在本篇攻略中,我们将使用 Go 语言实现一个极简的任务调度系统,包括实现任务的增、删、改、查和定时执行等功能。
2. 开始实现
2.1 系统设计
首先,我们需要设计出我们的系统。
这个系统有两个主要的结构,即任务(Task)和任务管理器(Task Manager)。
2.1.1 任务(Task)
一个任务包含如下信息:
- ID: 每个任务的唯一标识符。
- 周期: 任务执行的周期,可以是每天、每周、每月等等。
- 开始时间: 任务的开始时间。
- 结束时间: 任务的结束时间。
- 执行命令: 任务需要执行的命令。
2.1.2 任务管理器(Task Manager)
任务管理器用于管理所有的任务,提供如下功能:
- 添加任务: 添加新的任务,将任务存储到数据库中。
- 修改任务: 修改已有的任务,将修改后的任务存储到数据库中。
- 删除任务: 从数据库中删除指定的任务。
- 获取任务: 从数据库中获取指定的任务,可以根据任务的ID、名称等条件进行查询。
- 定时执行: 针对所有的任务,定时执行任务的命令。
2.2 数据存储
我们需要使用数据库来存储任务信息。在这里,我们选择使用MySQL数据库。需要用到的表为:
CREATE TABLE t_task (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL,
command varchar(1000) NOT NULL,
cycle int(11),
start_time datetime DEFAULT NULL,
end_time datetime DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.3 任务管理器实现
我们需要在任务管理器中实现增、删、改、查和定时执行等功能,具体实现见代码示例:
type TaskManager struct {
db *sql.DB // 数据库连接
}
// 新增任务
func (t *TaskManager) AddTask(task *Task) (int64, error) {
stmt, err := t.db.Prepare("INSERT INTO t_task(name, command, cycle, start_time, end_time) VALUES (?,?,?,?,?)")
if err != nil {
return 0, err
}
result, err := stmt.Exec(task.Name, task.Command, task.Cycle, task.StartTime, task.EndTime)
if err != nil {
return 0, err
}
return result.LastInsertId()
}
// 修改任务
func (t *TaskManager) ModifyTask(task *Task) error {
stmt, err := t.db.Prepare("UPDATE t_task SET name=?, command=?, cycle=?, start_time=?, end_time=? WHERE id=?")
if err != nil {
return err
}
_, err = stmt.Exec(task.Name, task.Command, task.Cycle, task.StartTime, task.EndTime, task.ID)
if err != nil {
return err
}
return nil
}
// 删除任务
func (t *TaskManager) DeleteTask(id int) error {
stmt, err := t.db.Prepare("DELETE FROM t_task WHERE id=?")
if err != nil {
return err
}
_, err = stmt.Exec(id)
if err != nil {
return err
}
return nil
}
// 获取任务
func (t *TaskManager) GetTask(id int) (*Task, error) {
stmt, err := t.db.Prepare("SELECT * FROM t_task WHERE id=?")
if err != nil {
return nil, err
}
row := stmt.QueryRow(id)
task := new(Task)
err = row.Scan(&task.ID, &task.Name, &task.Command, &task.Cycle, &task.StartTime, &task.EndTime)
if err != nil && err != sql.ErrNoRows{
return nil, err
}
return task, nil
}
// 定时执行
func (t *TaskManager) Run() error {
rows, err := t.db.Query("SELECT * FROM t_task")
if err != nil {
return err
}
for rows.Next() {
task := new(Task)
err := rows.Scan(&task.ID, &task.Name, &task.Command, &task.Cycle, &task.StartTime, &task.EndTime)
if err != nil {
return err
}
// 判断该任务是否在可执行的时间范围内
now := time.Now()
if task.StartTime.Before(now) && task.EndTime.After(now) {
// TODO: 执行任务的命令
}
}
}
2.4 任务调度器实现
我们需要使用定时器来实现任务的定时执行。在这里,我们选择使用Go标准库中的 time 包实现。具体实现见代码示例:
type Scheduler struct {
taskManager *TaskManager // 任务管理器
tick *time.Ticker // 定时器
stopChan chan bool // 停止信号
}
// 启动任务调度器
func (s *Scheduler) Start() {
s.tick = time.NewTicker(1 * time.Second)
s.stopChan = make(chan bool)
go func() {
for {
select {
case <-s.tick.C:
s.taskManager.Run() // 执行所有可执行的任务
case <-s.stopChan:
s.tick.Stop()
return
}
}
}()
}
// 停止任务调度器
func (s *Scheduler) Stop() {
s.stopChan <- true
}
2.5 示例
以上代码基本实现了任务调度系统的核心功能。接下来,我们给出两个示例来说明如何使用系统:
2.5.1 示例1:增加、修改、删除任务
func main() {
db, err := sql.Open("mysql", "user:password@tcp(localhost:3306)/taskdb?charset=utf8")
if err != nil {
log.Fatal(err)
}
taskManager := &TaskManager{
db: db,
}
// 新增任务
task1 := &Task{
Name: "Task1",
Cycle: 2 * 24 * 60 * 60, // 两天执行一次任务
StartTime: time.Date(2022, 1, 1, 0, 0, 0, 0, time.Local),
EndTime: time.Date(2022, 1, 31, 0, 0, 0, 0, time.Local),
Command: "echo 'Hello, World!' > /tmp/task1.log",
}
newTaskID, err := taskManager.AddTask(task1)
if err != nil {
log.Fatal(err)
}
log.Printf("Add Task1 success, new id is %d", newTaskID)
// 修改任务
modTask := &Task{
ID: 1,
Name: "Mod Task1",
Cycle: 24 * 60 * 60, // 一天执行一次任务
StartTime: time.Date(2022, 1, 1, 0, 0, 0, 0, time.Local),
EndTime: time.Date(2022, 1, 31, 0, 0, 0, 0, time.Local),
Command: "echo 'Hello, World! Modified' > /tmp/modtask1.log",
}
err = taskManager.ModifyTask(modTask)
if err != nil {
log.Fatal(err)
}
log.Printf("Mod Task1 success")
// 删除任务
err = taskManager.DeleteTask(1)
if err != nil {
log.Fatal(err)
}
log.Printf("Delete Task1 success")
}
2.5.2 示例2:使用任务调度器
func main() {
db, err := sql.Open("mysql", "user:password@tcp(localhost:3306)/taskdb?charset=utf8")
if err != nil {
log.Fatal(err)
}
taskManager := &TaskManager{
db: db,
}
scheduler := &Scheduler{
taskManager: taskManager,
}
// 启动任务调度器
scheduler.Start()
defer scheduler.Stop()
}
3. 总结
至此,我们已经完成了一个极简的任务调度系统的设计与实现。该系统使用了 MySQL 数据库与 Go 语言标准库中的 time 包,通过任务管理器与任务调度器的结合,实现了任务的增加、修改、删除、查询和定时执行等功能。
如果您还有任何疑问,请在评论区留言,我们将竭诚为您解答!
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:利用Go语言快速实现一个极简任务调度系统 - Python技术站