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 格式的数据自己处理:

相关推荐
源代码•宸16 小时前
Golang原理剖析(channel面试与分析)
开发语言·经验分享·后端·面试·golang·select·channel
moxiaoran575318 小时前
Go语言中的泛型
golang
加油201918 小时前
GO语言内存逃逸和GC机制
golang·内存管理·gc·内存逃逸
源代码•宸18 小时前
Golang原理剖析(channel源码分析)
开发语言·后端·golang·select·channel·hchan·sudog
liuyunshengsir18 小时前
golang Gin 框架下的大数据量 CSV 流式下载
开发语言·golang·gin
CHHC188018 小时前
golang 项目依赖备份
开发语言·后端·golang
老蒋每日coding19 小时前
AI智能体设计模式系列(八)—— 记忆管理模式
人工智能·设计模式·golang
且去填词1 天前
深入理解 GMP 模型:Go 高并发的基石
开发语言·后端·学习·算法·面试·golang·go
a程序小傲1 天前
京东Java面试被问:多活数据中心的流量调度和数据同步
java·开发语言·面试·职场和发展·golang·边缘计算
卜锦元2 天前
EchoChat搭建自己的音视频会议系统01-准备工作
c++·golang·uni-app·node.js·音视频