<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
任務排程(Task Scheduling)是很多軟體系統中的重要組成部分,字面上的意思是按照一定要求分配執行一些通常時間較長的指令碼或程式。在爬蟲管理平臺 Crawlab 中,任務排程是其中的核心模組,相信不少朋友會好奇如何編寫一個任務排程系統。本篇文章會教讀者用 Go 語言編寫一個非常簡單的任務排程系統。
我們首先理清一下思路,開發最小化任務排程器需要什麼。
整個流程如下:
我們通過 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 }
然後是任務排程的核心,定時任務。這裡我們使用 robfig/cron,Go 語言比較流行的定時任務庫。
現在建立 cron.go
檔案,輸入以下內容。其中 Cron
就是 robfig/cron
庫中的 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 佔位區域了。
同樣是 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) }
在這段程式碼中,我們實現了大部分邏輯,只在 AddJob
的 Cron.AddFunc
中第二個引數裡,剩下最後一部分執行任務的程式碼。下面將來實現一下。
現在需要新增任務執行的程式碼邏輯,咱們建立 exec.go
檔案,輸入以下內容。這裡我們用到了 Go 語言內建的 shell 執行管理庫 os/exec
,可以執行任何 shell 命令。
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) }) ...
OK,大功告成!現在我們可以試試執行這個極簡的任務排程器了。
在命令列中敲入 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
也就是說,執行成功了,大功告成!
本篇文章通過將 Go 語言幾個庫簡單組合,就開發出了一個極簡的任務排程系統。所用到的核心庫:
整個程式碼範例倉庫在 GitHub 上: https://github.com/tikazyq/codao-code/tree/main/2022-10/go-task-scheduler
到此這篇關於利用Go語言快速實現一個極簡任務排程系統的文章就介紹到這了,更多相關Go語言實現任務排程系統內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45