专栏首页GoUpUpGo 每日一库之 jobrunner

Go 每日一库之 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 格式的数据自己处理:

总结

大家如果发现好玩、好用的 Go 语言库,欢迎到 Go 每日一库 GitHub 上提交 issue?

参考

  1. jobrunner GitHub:https://github.com/bamzi/jobrunner
  2. Go 每日一库 GitHub:https://github.com/darjun/go-daily-lib

本文分享自微信公众号 - GoUpUp(GoUp-Up),作者:dj

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-09-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Go 每日一库之 commonregex

    有时,我们会遇到一些需要使用字符串的匹配和查找的任务。并且我们知道这种情况下,使用正则表达式是最简洁和优雅的。为了完成某个任务特地去系统地学习正则表达式费时费力...

    用户7731323
  • Go 每日一库之 jsonrpc

    在上一篇文章中我们介绍了 Go 标准库net/rpc的用法。在默认情况下,rpc库内部使用gob格式传输数据。我们仿造gob的编解码器实现了一个json格式的。...

    用户7731323
  • Go 每日一库之 quicktemplate

    最近在整理我们项目代码的时候,发现有很多活动的代码在结构和提供的功能上都非常相似。为了方便今后的开发,我花了一点时间编写了一个生成代码框架的工具,最大程度地降低...

    用户7731323
  • Tomcat Server处理一个http请求过程

    假设来自客户端的请求为:          http://localhost:8080/lizhx/lizhx_index.jsp 请求被发送到本机端口8080...

    YGingko
  • Git 配置多个 SSH-Key

    在 ~/.ssh 目录下新建一个 config 文件,添加如下内容(其中 Host 和 HostName 填写 git 服务器的域名,IdentityFile ...

    hedeqiang
  • 解决eclipse不能加载python安

    昨天遇到一个诡异的问题,安装了python第三方模块,但在eclipse始终不能使用,

    py3study
  • CentOS8部署KMS服务激活Office

    近期国内访问Github出现问题,此步骤可能会弹出连接失败,需在服务器修改Host后,方可执行下载Vlmcsd脚本的命令。

    InitCool
  • 从深度学习到机器人控制,2017 人工智能新开发工具盘点

    2017 年,在深度学习技术的加持下,CV、NLP、数据分析等领域全面开花,同时大量新开发工具和开源软件的涌现,降低了人工智能开发的门槛,加速了深度学习的普及。...

    AI研习社
  • python接口自动化(十八)--重定向(Location)(详解)

      在实际工作中,有些接口请求完以后会重定向到别的url,而你却需要重定向前的url。URL主要是针对虚拟空间而言,因为不是自己独立管理的服务器,所以无法正常...

    北京-宏哥
  • Github加载及下载问题

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    村雨遥

扫码关注云+社区

领取腾讯云代金券