PHP中高级工程师面试重点讲解视频课程
Go快速入门浅显易懂视频教程-基础篇
Go快速入门浅显易懂视频教程-中级篇
Go 写一个类似 cron 的定时任务管理器
阅读:1885 分享次数:0
  1. 用 Go 写一个类似 cron 的定时任务管理器。这个任务可以通过 HTTP API 去 添加/删除任务。

  2. 用 go 标准库,不用第三方库。

  3. go 不熟悉的话,用任何你熟悉的后端语言

目标

● 通过命令行启动启动服务

// 第一个命令行参数指定监听端口 $ ./gocron 4567
GoCron listening on 4567

● 创建新的任务

// 每 5 秒钟执行一次 date -R
// 子进程的输出直接用服务进程的标准输出即可
// 服务返回 HTTP 200:
{ ”ok”: true, ”id”: ”print-time”}
// 任务以存在,服务返回 HTTP 409:
{ ”ok”: false, ”error”: ”The task print-time already exists.”}// 用 JSON POST 去创建任务 curl -X POST localhost:4567 -d '
{
"id": "print-time", "cmd": "date", "args": ["-R"], "interval": 5000
}
'
// 每 5 秒钟执行一次 date -R
// 子进程的输出直接用服务进程的标准输出即可 // 服务返回 HTTP 200:
{ "ok": true, "id": "print-time"}
// 任务以存在,服务返回 HTTP 409:
{ "ok": false, "error": "The task print-time already exists."}

● 终止定时任务

// 服务返回, HTTP 200:
{ ”ok”: true, ”id”: ”print-time”}
// 没有该任务的话, HTTP 404:
{ ”ok”: false, ”error”: ”The task print-time is not found.”}curl -X DELETE localhost:4567 -d '
{
"id": "print-time",
} '
// 服务返回, HTTP 200:
{ "ok": true, "id": "print-time"}
// 没有该任务的话, HTTP 404:
{ "ok": false, "error": "The task print-time is not found."}



下面是答案——————


package main

import (
    "bufio"
    "encoding/json"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "net/http"
    "os"
    "os/exec"
    "time"
    //"runtime/debug"
)

var Debug = true
var tickMaps = make(map[string]*time.Timer)

type BodyJson struct {
    Id       string
    Cmd      string
    Args     []string
    Interval time.Duration
}

type DBodyJson struct {
    Id string
}

func newTimer(id string, cmd string, args []string, interval time.Duration) {
    tickMaps[id] = time.NewTimer(time.Millisecond * interval)
    for {
        select {
        case <-tickMaps[id].C:
            tCmd := exec.Command(cmd, args...)
            stdout, err := tCmd.StdoutPipe()
            if err != nil {
                fmt.Println(err)
                break
            }
            tCmd.Start()
            reader := bufio.NewReader(stdout)
            for {
                line, err2 := reader.ReadString('\n')
                if err2 != nil || io.EOF == err2 {
                    break
                }
                fmt.Println(line)
            }
            tCmd.Wait()
            fmt.Println(8888)
            tickMaps[id].Reset(time.Millisecond * interval)
        }
    }
}

func HelloWorld(w http.ResponseWriter, r *http.Request) {
    fmt.Println(r.Method)
    if r.Method == "POST" {
        body, err := ioutil.ReadAll(r.Body)
        if err != nil {
            fmt.Printf("read body err, %v\n", err)
            return
        }
        var tbody BodyJson
        if err = json.Unmarshal(body, &tbody); err != nil {
            fmt.Printf("Unmarshal err, %v\n", err)
            return
        }
        id := tbody.Id
        cmd := tbody.Cmd
        args := tbody.Args
        interval := tbody.Interval

        if tickMaps[id] == nil {
            go newTimer(id, cmd, args, interval)
            data := map[string]interface{}{"id": id, "ok": true}
            d, _ := json.Marshal(data)
            w.Header().Set("Content-Type", "text/json")
            w.Write([]byte(d))
        } else {
            data := map[string]interface{}{"error": "this " + id + "already exists.", "ok": false}
            d, _ := json.Marshal(data)
            w.Header().Set("Content-Type", "text/json")
            w.Write([]byte(d))
        }
    } else if r.Method == "DELETE" {
        body, err := ioutil.ReadAll(r.Body)
        if err != nil {
            fmt.Printf("read body err, %v\n", err)
            return
        }
        var tbody DBodyJson
        if err = json.Unmarshal(body, &tbody); err != nil {
            fmt.Printf("Unmarshal err, %v\n", err)
            return
        }
        id := tbody.Id
        if tickMaps[id] != nil && tickMaps[id].Stop() {
            data := map[string]interface{}{"id": id, "ok": true}
            d, _ := json.Marshal(data)
            w.Header().Set("Content-Type", "text/json")
            w.Write([]byte(d))
        } else {
            data := map[string]interface{}{"error": "this " + id + "not found", "ok": false}
            d, _ := json.Marshal(data)
            w.Header().Set("Content-Type", "text/json")
            w.Write([]byte(d))
        }
    }
}

func main() {
    //debug.PrintStack()

    if len(os.Args) != 2 {
        fmt.Println("no port param")
        return
    }
    port := os.Args[1]

    http.HandleFunc("/", HelloWorld)

    fmt.Println("GoCron listening on " + port)
    err := http.ListenAndServe(":"+port, nil)
    if err != nil {
        log.Fatal("ListenAndServe:", err)
        return
    }

}


感觉本站内容不错,读后有收获?