Golang in Action: 최소 작업 스케줄링 시스템을 신속하게 구현하는 방법
소개
작업 예약은 소프트웨어 시스템에서 가장 중요한 기능 중 하나이며, 말 그대로 특정 사양에 따라 긴 작업이나 스크립트를 할당하고 실행하는 것을 의미합니다. 웹 크롤러 관리 플랫폼Crawlab에서 작업 예약은 핵심 모듈 역할을 하며, 이를 처음부터 구축하는 방법이 궁금할 수 있습니다. 이 기사에서는 Go로 간단하지만 유용한 작업 스케줄러를 구축하는 방법을 소개합니다.
아이디어
태스크 스케줄링 시스템에 필요한 사항에 초점을 맞추겠습니다.
아래는 기본적인 과정입니다.
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
을 생성합니다. 변수 Cron
는 robfig/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의 몇 가지 라이브러리를 간단하게 조합하여 최소 작업 스케줄링 시스템을 개발하는 방법을 소개했습니다.
핵심 라이브러리:
전체 프로젝트의 코드는 GitHub에 있습니다: https://github.com/tikazyq/codao-code/tree/main/2022-10/go-task-scheduler
Reference
이 문제에 관하여(Golang in Action: 최소 작업 스케줄링 시스템을 신속하게 구현하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/tikazyq/golang-in-action-how-to-quickly-implement-a-minimal-task-scheduling-system-fel텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)