应用优雅退出

pull/21/merge
ouqiang 2017-05-04 18:05:25 +08:00
parent ebb5139a7b
commit 4c07b02706
4 changed files with 71 additions and 8 deletions

View File

@ -2,7 +2,7 @@
# gocron - 定时任务web管理系统 # gocron - 定时任务web管理系统
# 项目简介 # 项目简介
使用Go语言开发的定时任务集中调度和管理系统, 用于替代Linux-crontab 使用Go语言开发的定时任务集中调度和管理系统, 用于替代Linux-crontab [查看文档](https://github.com/ouqiang/gocron/wiki)
## 功能特性 ## 功能特性
* 支持任务CURD * 支持任务CURD

View File

@ -12,6 +12,7 @@ import (
"github.com/ouqiang/gocron/service" "github.com/ouqiang/gocron/service"
"github.com/ouqiang/gocron/models" "github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/modules/setting" "github.com/ouqiang/gocron/modules/setting"
"time"
) )
// web服务器默认端口 // web服务器默认端口
@ -45,6 +46,7 @@ func run(ctx *cli.Context) {
// 捕捉信号,配置热更新等 // 捕捉信号,配置热更新等
go catchSignal() go catchSignal()
m := macaron.Classic() m := macaron.Classic()
// 注册路由 // 注册路由
routers.Register(m) routers.Register(m)
// 注册中间件. // 注册中间件.
@ -110,7 +112,25 @@ func catchSignal() {
logger.Info("收到信号 -- ", s) logger.Info("收到信号 -- ", s)
switch s { switch s {
case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM: case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM:
os.Exit(1) shutdown()
} }
} }
}
func shutdown() {
logger.Info("应用准备退出\n停止任务调度")
serviceTask := new(service.Task)
// 停止所有任务调度
serviceTask.StopAll()
taskNumInRunning := service.TaskNum.Num()
logger.Infof("正在运行的任务有%d个", taskNumInRunning)
for {
if taskNumInRunning <= 0 {
break
}
time.Sleep(3 * time.Second)
taskNumInRunning = service.TaskNum.Num()
}
logger.Info("已退出")
os.Exit(0)
} }

View File

@ -81,9 +81,11 @@ func write(level Level, v ...interface{}) {
defer logger.Flush() defer logger.Flush()
content := "" content := ""
pc, file, line, ok := runtime.Caller(2) if macaron.Env == macaron.DEV {
if ok { pc, file, line, ok := runtime.Caller(2)
content = fmt.Sprintf("#%s#%s#%d行#", file, runtime.FuncForPC(pc).Name(), line) if ok {
content = fmt.Sprintf("#%s#%s#%d行#", file, runtime.FuncForPC(pc).Name(), line)
}
} }
switch level { switch level {
@ -105,9 +107,11 @@ func writef(level Level, format string, v ...interface{}) {
defer logger.Flush() defer logger.Flush()
content := "" content := ""
pc, file, line, ok := runtime.Caller(2) if macaron.Env == macaron.DEV {
if ok { pc, file, line, ok := runtime.Caller(2)
content = fmt.Sprintf("#%s#%s#%d行#", file, runtime.FuncForPC(pc).Name(), line) if ok {
content = fmt.Sprintf("#%s#%s#%d行#", file, runtime.FuncForPC(pc).Name(), line)
}
} }
format = content + format format = content + format

View File

@ -12,10 +12,40 @@ import (
"fmt" "fmt"
"github.com/ouqiang/gocron/modules/httpclient" "github.com/ouqiang/gocron/modules/httpclient"
"github.com/ouqiang/gocron/modules/notify" "github.com/ouqiang/gocron/modules/notify"
"sync"
) )
// 定时任务调度管理器
var Cron *cron.Cron var Cron *cron.Cron
// 同一任务是否有实例处于运行中
var runInstance Instance var runInstance Instance
// 任务计数-正在运行中的任务
var TaskNum TaskCount
// 任务计数
type TaskCount struct {
num int
sync.RWMutex
}
func (c *TaskCount) Add() {
c.Lock()
defer c.Unlock()
c.num += 1
}
func (c *TaskCount) Done() {
c.Lock()
defer c.Unlock()
c.num -= 1
}
func (c *TaskCount) Num() int {
c.RLock()
defer c.RUnlock()
return c.num
}
// 任务ID作为Key, 不会出现并发写, 不加锁 // 任务ID作为Key, 不会出现并发写, 不加锁
type Instance struct { type Instance struct {
@ -54,6 +84,8 @@ func (task *Task) Initialize() {
Cron = cron.New() Cron = cron.New()
Cron.Start() Cron.Start()
runInstance = Instance{make(map[int]bool)} runInstance = Instance{make(map[int]bool)}
TaskNum = TaskCount{0, sync.RWMutex{}}
taskModel := new(models.Task) taskModel := new(models.Task)
taskList, err := taskModel.ActiveList() taskList, err := taskModel.ActiveList()
if err != nil { if err != nil {
@ -91,6 +123,11 @@ func (task *Task) Add(taskModel models.TaskHost) {
} }
} }
// 停止所有任务
func (task *Task) StopAll() {
Cron.Stop()
}
// 直接运行任务 // 直接运行任务
func (task *Task) Run(taskModel models.TaskHost) { func (task *Task) Run(taskModel models.TaskHost) {
go createJob(taskModel)() go createJob(taskModel)()
@ -231,6 +268,8 @@ func createJob(taskModel models.TaskHost) cron.FuncJob {
return nil return nil
} }
taskFunc := func() { taskFunc := func() {
TaskNum.Add()
defer TaskNum.Done()
taskLogId := beforeExecJob(&taskModel) taskLogId := beforeExecJob(&taskModel)
if taskLogId <= 0 { if taskLogId <= 0 {
return return