golang执行异步任务的第三方库jobrunner库实践

简介

我们在 Web 开发中时常会遇到这样的需求,执行一个操作之后,需要给用户一定形式的通知。例如,用户下单之后通过邮件发送电子发票,网上购票支付后通过短信发送车次信息。但是这类需求并不需要非常及时,如果放在请求流程中处理,会影响请求的响应时间。这类任务我们一般使用异步的方式来执行。jobrunner就是其中一个用来执行异步任务的 Go 语言库。得益于强大的cron库,再搭配jobrunner的任务状态监控,jobrunner非常易于使用。

快速使用

本文使用 Go Modules。

创建目录并初始化:

复制代码
$ mkdir jobrunner && cd jobrunner
$ go mod init github.com/darjun/go-daily-lib/jobrunner

安装jobrunner

复制代码
$ go get -u github.com/bamzi/jobrunner

使用:

复制代码
package main

import (
  "fmt"
  "time"

  "github.com/bamzi/jobrunner"
)

type GreetingJob struct {
  Name string
}

func (g GreetingJob) Run() {
  fmt.Println("Hello, ", g.Name)
}

func main() {
  jobrunner.Start()
  jobrunner.Schedule("@every 5s", GreetingJob{Name: "dj"})

  time.Sleep(10 * time.Second)
}

我们创建一个任务,每隔 5s 打印一条欢迎信息。任务的创建和执行与cron完全相同,详细使用见我前面的一篇博文

注意,jobrunner需要先Start(),然后再添加任务。因为在Start()中创建MainCron对象,先添加任务会panic!!!

注意main函数尾的time.Sleep(10 * time.Second),因为主 goroutine 结束之后整个程序就退出了,jobrunner中的任务就没有机会被执行了。加上time.Sleep是为了让大家能看到输出,实际使用中不会这样做。

与 web 框架整合

jobrunner能很方便地与当前常见的 Web 框架整合,如Gin/Echo/Martini/Beego/Revel等。下面通过一个简单的例子演示如何在 Gin 中使用jobrunner:用户登录时给他的邮箱发送一封邮件。

首先需要安装相应的库:

复制代码
$ go get -u github.com/gin-gonic/gin
$ github.com/jordan-wright/email

编写代码:

package main

import (

"fmt"

"net/smtp"

"time"

"github.com/bamzi/jobrunner"

"github.com/gin-gonic/gin"

"github.com/jordan-wright/email"

)

type EmailJob struct {

Name string

Email string

}

type User struct {

Name string `form:"name"`

Email string `form:"email"`

}

func (j EmailJob) Run() {

e := email.NewEmail()

e.From = "leedarjun@126.com"

e.To = \[\]string{j.Email}

e.Cc = \[\]string{"leedarjun@126.com"}

e.Subject = "Welcome To Awesome-Web"

e.Text = \[\]byte(fmt.Sprintf(`

Hello, %s

Welcome Back

`, j.Name))

err := e.Send("smtp.126.com:25", smtp.PlainAuth("", "leedarjun@126.com", "yyyyyy", "smtp.126.com"))

if err != nil {

fmt.Printf("failed to send email to %s, err:%v", j.Name, err)

}

}

func login(c *gin.Context) {

var u User

if c.ShouldBind(&u) == nil {

c.String(200, "login success")

jobrunner.In(5*time.Second, EmailJob{Name: u.Name, Email: u.Email})

} else {

c.String(404, "login failed")

}

}

func main() {

r := gin.Default()

r.GET("/login", login)

r.Run(":8888")

}

这里只是为了简单演示,我们编写了一个简陋的login函数处理登录,传入nameemail,然后给该email发送邮件。email库的详细使用可以查看我之前的博文了解。

只需要在浏览器中输入http://localhost:8888/login?name=dj&email=935653229@qq.com,我的 QQ 邮箱就能收到邮件:

监控

jobrunner内置了一个监控模块,可以很方便地通过网页或者 API 获取当前的任务状态数据:

package main

import (

"fmt"

"html/template"

"os"

"time"

"github.com/bamzi/jobrunner"

"github.com/gin-gonic/gin"

)

type GreetingJob struct {

Name string

}

func (g GreetingJob) Run() {

fmt.Println("Hello,", g.Name)

}

type EmailJob struct {

Email string

}

func (e EmailJob) Run() {

fmt.Println("Send,", e.Email)

}

func main() {

r := gin.Default()

jobrunner.Start()

jobrunner.Every(5*time.Second, GreetingJob{Name: "dj"})

jobrunner.Every(10*time.Second, EmailJob{Email: "935653229@qq.com"})

r.GET("/jobrunner/json", JobJson)

r.GET("/jobrunner/html", JobHtml)

r.Run(":8888")

}

func JobJson(c *gin.Context) {

c.JSON(200, jobrunner.StatusJson())

}

func JobHtml(c *gin.Context) {

t, err := template.ParseFiles(os.Getenv("GOPATH") + "/src/github.com/bamzi/jobrunner/views/Status.html")

if err != nil {

c.JSON(400, "error")

}

t.Execute(c.Writer, jobrunner.StatusPage())

}

运行之后,在浏览器中输入http://localhost:8888/jobrunner/html查看任务状态:

这里显示任务名、任务 ID、状态、上次运行时间、下次运行时间以及处理延迟。

我们还可以通过http://localhost:8888/jobrunner/json获取原始 JSON 格式的数据自己处理:

相关推荐
进击的程序猿~11 小时前
Go Interface源码深度解析指南
开发语言·后端·golang
—Qeyser14 小时前
Sponge 脚手架快速创建后端API及接口使用完整教程
golang
不爱洗脚的小滕16 小时前
【Golang】Go 语言实现高可用、用户态感知与多端广播的服务端 SSE 架构
开发语言·架构·golang
报错小能手16 小时前
Go 简介
开发语言·后端·golang
golang学习记1 天前
Go 项目使用docker compose的正确方式
开发语言·docker·golang
2501_931803751 天前
深入理解 GORM:从模型定义到关联查询的核心原理
golang
似璟如你1 天前
Java 开发者的 Go 语法基础:从 0 开始快速上手 Go
java·开发语言·后端·golang·go·编程语言
microrain2 天前
从监控孤岛到视联一体:SagooIoT视频监控中心的设计实践
物联网·golang·开源·sagooiot
GoFly开发者3 天前
GoFly 社区 GMQT|国产自研 MQTT‑Broker,打造私有化物联网消息底座
物联网·mqtt·golang·mqtt broker·mqtt私有化部署