Golang in Action: 최소 작업 스케줄링 시스템을 신속하게 구현하는 방법

19415 단어 gocron

소개



작업 예약은 소프트웨어 시스템에서 가장 중요한 기능 중 하나이며, 말 그대로 특정 사양에 따라 긴 작업이나 스크립트를 할당하고 실행하는 것을 의미합니다. 웹 크롤러 관리 플랫폼Crawlab에서 작업 예약은 핵심 모듈 역할을 하며, 이를 처음부터 구축하는 방법이 궁금할 수 있습니다. 이 기사에서는 Go로 간단하지만 유용한 작업 스케줄러를 구축하는 방법을 소개합니다.

아이디어



태스크 스케줄링 시스템에 필요한 사항에 초점을 맞추겠습니다.
  • 사용자 인터페이스: API
  • 스케줄러: 크론
  • 작업 실행: 집행자

  • 아래는 기본적인 과정입니다.



    HTTP API를 사용하여 예약된 작업을 생성할 수 있으며 실행자는 사양에 따라 주기적으로 스크립트를 실행합니다.

    동작



    사용자 인터페이스



    먼저 기본 구조를 만들어 봅시다. 이제 루트 디렉터리 아래에 파일main.go을 만들고 아래 내용을 입력합니다. gin는 Go로 작성된 널리 사용되는 API 엔진입니다.

    package main
    
    import (
        "fmt"
        "github.com/gin-gonic/gin"
        "os"
    )
    
    func main() {
        // api engine
        app := gin.New()
    
        // api routes
        app.GET("/jobs", GetJobs)
        app.POST("/jobs", AddJob)
        app.DELETE("/jobs", DeleteJob)
    
        // run api on port 9092
      if err := app.Run(":9092"); err != nil {
            _, err = fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }
    }
    
    


    그런 다음 아래와 같은 내용으로 파일api.go을 생성합니다. 여기에는 구현이 없지만 대신 자리 표시자가 있습니다.

    package main
    
    import "github.com/gin-gonic/gin"
    
    func GetJobs(c *gin.Context) {
        // TODO: implementation here
    }
    
    func AddJob(c *gin.Context) {
        // TODO: implementation here
    }
    
    func DeleteJob(c *gin.Context) {
        // TODO: implementation here
    }
    
    


    일정 작업



    이제 작업 스케줄러의 핵심인 cron 작업을 구현해 보겠습니다. 우리는 Go로 작성된 평판이 좋은 cron 라이브러리인 robfig/cron 을 사용할 것입니다.

    이제 아래와 같은 내용으로 새 파일cron.go을 생성합니다. 변수 Cronrobfig/cron의 클래스에서 시작된 인스턴스입니다.

    package main
    
    import "github.com/robfig/cron"
    
    func init() {
        // start to run
        Cron.Run()
    }
    
    // Cron create a new cron.Cron instance
    var Cron = cron.New()
    
    


    작업 스케줄러 인스턴스가 생성되면 이제 이전에 생성한 자리 표시자에 핵심 코드를 채울 수 있습니다.
    api.go에서 다시 핵심 코드를 추가해 보겠습니다.

    package main
    
    import (
        "github.com/gin-gonic/gin"
        "github.com/robfig/cron/v3"
        "net/http"
        "strconv"
    )
    
    func GetJobs(c *gin.Context) {
        // return a list of cron job entries
        var results []map[string]interface{}
        for _, e := range Cron.Entries() {
            results = append(results, map[string]interface{}{
                "id":   e.ID,
                "next": e.Next,
            })
        }
        c.JSON(http.StatusOK, Cron.Entries())
    }
    
    func AddJob(c *gin.Context) {
        // post JSON payload
        var payload struct {
            Cron string `json:"cron"`
            Exec string `json:"exec"`
        }
        if err := c.ShouldBindJSON(&payload); err != nil {
            c.AbortWithStatus(http.StatusBadRequest)
            return
        }
    
        // add cron job
        eid, err := Cron.AddFunc(payload.Cron, func() {
        // TODO: implementation here
        })
        if err != nil {
            c.AbortWithStatusJSON(http.StatusInternalServerError, map[string]interface{}{
                "error": err.Error(),
            })
            return
        }
    
        c.AbortWithStatusJSON(http.StatusOK, map[string]interface{}{
            "id": eid,
        })
    }
    
    func DeleteJob(c *gin.Context) {
        // cron job entry id
        id := c.Param("id")
        eid, err := strconv.Atoi(id)
        if err != nil {
            c.AbortWithStatus(http.StatusBadRequest)
            return
        }
    
        // remove cron job
        Cron.Remove(cron.EntryID(eid))
    
        c.AbortWithStatus(http.StatusOK)
    }
    
    


    코드 블록에서 우리는 가장 많은 로직을 구현했습니다. 유일하게 남은 부분은 Cron.AddFunc 함수의 AddJob에 있는 두 번째 매개변수의 실제 실행 논리입니다.

    태스크 실행



    이제 작업 실행 로직을 구현해 보겠습니다. 먼저 아래 내용으로 새 파일exec.go을 만듭니다. 여기에서는 내장 Golang 라이브러리os/exec를 사용하여 모든 셸 명령을 실행했습니다.

    package main
    
    import (
        "fmt"
        "os"
        "os/exec"
        "strings"
    )
    
    func ExecuteTask(execCmd string) {
        // execute command string parts, delimited by space
        execParts := strings.Split(execCmd, " ")
    
        // executable name
        execName := execParts[0]
    
        // execute command parameters
        execParams := strings.Join(execParts[1:], " ")
    
        // execute command instance
        cmd := exec.Command(execName, execParams)
    
        // run execute command instance
        if err := cmd.Run(); err != nil {
            _, err = fmt.Fprintln(os.Stderr, err)
            fmt.Println(err.Error())
        }
    }
    
    


    아주 잘. 이제 이 부분을 이전 자리 표시자에 넣을 수 있습니다.

    ...
        // add cron job
        eid, _ := Cron.AddFunc(payload.Cron, func() {
            ExecuteTask(payload.Exec)
        })
    ...
    


    최종 결과



    좋아, 모두 끝났어! 이제 우리는 이 최소 작업 스케줄러를 가지고 놀 수 있습니다.

    명령 프롬프트를 열고 go run . 를 입력하면 API 엔진이 시작됩니다.

    [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
     - using env:   export GIN_MODE=release
     - using code:  gin.SetMode(gin.ReleaseMode)
    
    [GIN-debug] GET    /jobs                     --> main.GetJobs (1 handlers)
    [GIN-debug] POST   /jobs                     --> main.AddJob (1 handlers)
    [GIN-debug] DELETE /jobs/:id                 --> main.DeleteJob (1 handlers)
    [GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
    Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
    [GIN-debug] Listening and serving HTTP on :9092
    
    


    이제 다른 명령 프롬프트를 열고 curl -X POST -d '{"cron":"* * * * *","exec":"touch /tmp/hello.txt"}' http://localhost:9092/jobs 를 입력하면 아래와 같은 결과가 나타납니다. 즉, ID가 1인 일정 작업이 생성되고 매분 업데이트/tmp/hello.txt됩니다.

    {"id":1}
    


    그런 다음 이 프롬프트에 명령curl http://localhost:9092/jobs을 입력합니다.

    [{"id":1,"next":"2022-10-03T12:46:00+08:00"}]
    


    이는 다음 실행이 1분 후임을 의미합니다.

    잠시 기다렸다가 실행ls -l /tmp/hello.txt하면 아래 결과가 표시됩니다.

    -rw-r--r--  1 marvzhang  wheel     0B Oct  3 12:46 /tmp/hello.txt
    


    완벽하게 작동한다는 의미입니다!

    결론



    이 기사에서는 Golang의 몇 가지 라이브러리를 간단하게 조합하여 최소 작업 스케줄링 시스템을 개발하는 방법을 소개했습니다.

    핵심 라이브러리:
  • gin
  • robfig/cron
  • 운영 체제/exec

  • 전체 프로젝트의 코드는 GitHub에 있습니다: https://github.com/tikazyq/codao-code/tree/main/2022-10/go-task-scheduler

    좋은 웹페이지 즐겨찾기