优雅关闭任务
妥善停止任务
优雅关闭任务 是 CoddyKit 上的免费 Go Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。
优雅地停止作业
如果调度器在作业执行过程中被终止,可能会损坏数据或留下未完成的工作。优雅关闭意味着:停止接受新的运行请求,让正在执行的作业完成(最多等到截止时间),然后退出。
监听信号
捕获 OS 信号,例如 SIGINT(Ctrl+C)和 SIGTERM(编排器停止),以便按计划关闭。
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig
fmt.Println("shutting down")signal.NotifyContext
Go 1.16+ 提供了一个简洁的辅助函数,可在收到信号时取消上下文。
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
<-ctx.Done()停止调度器
使用 robfig/cron 时,c.Stop() 会返回一个上下文;所有正在运行的作业完成后,该上下文就会结束。请等待它,以便排空作业。
ctx := c.Stop() // stops scheduling, returns ctx
<-ctx.Done() // wait for running jobs
fmt.Println("all jobs finished")向作业传递取消信号
将上下文传入每个作业,以便长时间运行的工作在关闭开始时能够及时中止。
func job(ctx context.Context) {
select {
case <-time.After(time.Hour):
case <-ctx.Done():
return // bail out early
}
}限制等待时间
请不要无限等待卡住的作业。使用超时上下文,即使某个作业挂起,关闭也能完成。
shutCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()自定义调度器中的 WaitGroups
如果您使用协程自行实现调度器,请通过 sync.WaitGroup 跟踪它们,并在关闭期间调用 Wait()。
var wg sync.WaitGroup
wg.Add(1)
go func() { defer wg.Done(); doWork() }()
// shutdown:
wg.Wait()避免开始新工作
一旦开始关闭,计时器或 cron 调度器就必须停止触发。关闭完成通道或取消上下文可确保循环检测到信号,并停止安排新的运行。
幂等性很有帮助
请将作业设计为可安全重复运行。如果作业执行到一半被终止,并在重启后重试,幂等逻辑可以避免重复产生影响(重复发送邮件、重复扣款)。
完整模式
综合起来:一个在收到信号时通知的上下文、一个会返回排空上下文的 cron Stop,以及一个有上限的超时。这是计划服务的标准优雅关闭框架。
可运行示例:使用上下文优雅停止
这个自包含程序会运行一个周期性工作器,并通过取消上下文优雅地停止它,同时等待正在执行的触发完成。
package main
import (
"context"
"fmt"
"sync"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
t := time.NewTicker(5 * time.Millisecond)
defer t.Stop()
for {
select {
case <-t.C:
fmt.Println("working")
case <-ctx.Done():
fmt.Println("stopping cleanly")
return
}
}
}()
time.Sleep(17 * time.Millisecond)
cancel() // signal shutdown
wg.Wait() // wait for worker to finish
fmt.Println("shutdown complete")
}快速检查
测试您对作业优雅关闭的理解。
回顾
您已经学习了如何优雅地关闭作业:
- 捕获 SIGINT/SIGTERM,最好通过
signal.NotifyContext cron.Stop()会返回一个等待正在运行的作业完成的上下文- 将上下文传递给作业,并使用超时限制等待时间
- 使作业具备幂等性,从而确保重试安全
用 AI 导师学习 Go — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 51
- 课程
- 203
常见问题解答
「优雅关闭任务」课时是免费的吗?
是的 — 「优雅关闭任务」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。
「优雅关闭任务」这节课中我会学到什么?
妥善停止任务 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Go Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「优雅关闭任务」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Go Academy 课中编写并运行代码吗?
能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。