beego网站开发 定时执行任务
上网查了下相关资料,基本上都介绍的是github.com\robfig\cron这个包来执行定时任务,试了下确实可以执行。但是此包下没有删除任务的方法,只有暂停的方法(Stop),若要停止之前的任务只执行新定义的任务,除非服务器重启再定义新任务。后来又参考了一下其他人的建议,采用了github.com\jakecoffman\cron这个包。后者是在前者的基础上做了一定的修改,给每个任务添加的一个
上网查了下相关资料,基本上都介绍的是github.com\robfig\cron这个包来执行定时任务,试了下确实可以执行。但是此包下没有删除任务的方法,只有暂停的方法(Stop),若要停止之前的任务只执行新定义的任务,除非服务器重启再定义新任务。后来又参考了一下其他人的建议,采用了github.com\jakecoffman\cron这个包。后者是在前者的基础上做了一定的修改,给每个任务添加的一个新属性Name,然后新添加一个remove(name)方法,用来删除指定名字的任务,经测试使用后可正常删除任务,只不过之前的计划任务名得新建一个全局变量来存储。
以下先简单介绍下定义时间集合的信息:
字段名 | 是否必须 | 允许的值 | 允许的特定字符 |
秒(Seconds) | 是 | 0-59 |
* / , -
|
分(Minutes) | 是 | 0-59 |
* / , -
|
时(Hours) | 是 | 0-23 |
* / , -
|
日(Day of month) | 是 | 1-31 |
* / , – ?
|
月(Month) | 是 | 1-12 or JAN-DEC |
* / , -
|
星期(Day of week) | 否 | 0-6 or SUM-SAT |
* / , – ?
|
注:
1)月(Month)和星期(Day of week)字段的值不区分大小写,如:SUN、Sun 和 sun 是一样的。
2)星期
(Day of week)字段如果没提供,相当于是 *
2、特殊字符说明
1)星号(*)
表示 cron 表达式能匹配该字段的所有值。如在第5个字段使用星号(month),表示每个月
回到顶部
2)斜线(/)
表示增长间隔,如第1个字段(minutes) 值是 3-59/15,表示每小时的第3分钟开始执行一次,之后每隔 15 分钟执行一次(即 3、18、33、48 这些时间点执行),这里也可以表示为:3/15
回到顶部
3)逗号(,)
用于枚举值,如第6个字段值是 MON,WED,FRI,表示 星期一、三、五 执行
回到顶部
4)连字号(-)
表示一个范围,如第3个字段的值为 9-17 表示 9am 到 5pm 直接每个小时(包括9和17)
回到顶部
5)问号(?)
只用于 日(Day of month) 和 星期(Day of week),表示不指定值,可以用于代替 *
在beego下使用,我简单的封装一下(代码不是我写的,而且写的很随意,也只保证了可用的程度),自定义package jobs如下:
job.go源码:
package jobs
import (
"github.com/astaxie/beego"
"github.com/jakecoffman/cron"
"reflect"
"runtime/debug"
"sync"
"sync/atomic"
)
type Job struct {
Name string
inner cron.Job
status uint32
running sync.Mutex
}
const UNNAMED = "(unnamed)"
func New(job cron.Job) *Job {
name := reflect.TypeOf(job).Name()
if name == "Func" {
name = UNNAMED
}
return &Job{
Name: name,
inner: job,
}
}
func (j *Job) Status() string {
if atomic.LoadUint32(&j.status) > 0 {
return "RUNNING"
}
return "IDLE"
}
func (j *Job) Run() {
// If the job panics, just print a stack trace.
// Don't let the whole process die.
defer func() {
if err := recover(); err != nil {
beego.Error("%v", debug.Stack())
}
}()
if !selfConcurrent {
j.running.Lock()
defer j.running.Unlock()
}
if workPermits != nil {
workPermits <- struct{}{}
defer func() { <-workPermits }()
}
atomic.StoreUint32(&j.status, 1)
defer atomic.StoreUint32(&j.status, 0)
j.inner.Run()
}
jobrunner.go源码:
// A job runner for executing scheduled or ad-hoc tasks asynchronously from HTTP requests.
//
// It adds a couple of features on top of the cron package to make it play nicely with Revel:
// 1. Protection against job panics. (They print to ERROR instead of take down the process)
// 2. (Optional) Limit on the number of jobs that may run simulatenously, to
// limit resource consumption.
// 3. (Optional) Protection against multiple instances of a single job running
// concurrently. If one execution runs into the next, the next will be queued.
// 4. Cron expressions may be defined in app.conf and are reusable across jobs.
// 5. Job status reporting.
package jobs
import (
//"fmt"
"github.com/jakecoffman/cron"
"time"
)
// Callers can use jobs.Func to wrap a raw func.
// (Copying the type to this package makes it more visible)
//
// For example:
// jobs.Schedule("cron.frequent", jobs.Func(myFunc))
type Func func()
func (r Func) Run() { r() }
//定时执行任务
func Schedule(spec string, job cron.Job, name string) error {
sched := cron.Parse(spec)
/*if err != nil {
return err
}*/
MainCron.Schedule(sched, New(job), name)
return nil
}
// Run the given job at a fixed interval.
// The interval provided is the time between the job ending and the job being run again.
// The time that the job takes to run is not included in the interval.
func Every(duration time.Duration, job cron.Job, name string) {
MainCron.Schedule(cron.Every(duration), New(job), name)
}
// Run the given job right now.
func Now(job cron.Job) {
go New(job).Run()
}
// Run the given job once, after the given delay.
func In(duration time.Duration, job cron.Job) {
go func() {
time.Sleep(duration)
New(job).Run()
}()
}
// 暂停所有任务
func Stop() {
MainCron.Stop()
}
//清空任务
func Remove(name string) {
MainCron.RemoveJob(name)
}
plugin.go源码:
package jobs
import (
"github.com/jakecoffman/cron"
)
const DEFAULT_JOB_POOL_SIZE = 10
var (
// Singleton instance of the underlying job scheduler.
MainCron *cron.Cron
// This limits the number of jobs allowed to run concurrently.
workPermits chan struct{}
// Is a single job allowed to run concurrently with itself?
selfConcurrent bool
)
func init() {
MainCron = cron.New()
workPermits = make(chan struct{}, DEFAULT_JOB_POOL_SIZE)
selfConcurrent = false
MainCron.Start()
}
因为是网站执行定时任务,这边我是将任务是否开启的控制权放在前端页面,通过点击按钮访问controller方法,从而启动任务,所以我把任务执行方法放在了controller中。通过如下方式调用:
import (
//其他引用包我都省略了
"hnnaserver/src/jobs"
)
type job struct {
user string
province int64
method int64
count int64
}
//任务执行的方法
func (j *job) Run() {
//do something....
}
func (this *SystemController) AutoDisCus() {
spec := "0 0 15 * * 1-5"//定义执行时间点 参照上面的说明可知 执行时间为 周一至周五每天15:00:00执行
//spec := "*/5 * * * * ?" //这是网上一般的例子 即每5s执行一次
j := &job{user, province, method, count}
jobs.Schedule(spec, j, taskName) //3个参数分别为 执行时间(规则之间介绍过) 要执行的任务 任务名
}
若要删除某项任务,则调用remove方法即可,如下:
jobs.Remove(tasksName)
更多推荐
所有评论(0)