Go開発者必見!gocronでタスクを毎日・週次・月次で効率的に実行する方法
簡単で流暢なGoのcronスケジューリング。これはjasonlvhit/gocronからのフォークです。
Goプログラミング言語自体を使用して、タスクを毎日、毎週、毎月、一回限り、またはcronを使用して実行するようにスケジュールすることができます。
私はmicronaut[Javaフレームワーク]の@Scheduledアノテーションに慣れており、Java世界では本当に素晴らしいものでした。しかし、Go言語の世界では、私はginフレームワークを使用していました。毎日午前12時にタスクを実行する必要がありました。3つの解決策がありました:
*nixのcronを使用する
スケジューラを自分で実装する
サードパーティのパッケージを使用する
はい、私はオプション3を選択しました。なぜなら、それが簡単で、車輪を再発明する必要がないからです。
私は2つのパッケージを見つけました:
https://github.com/jasonlvhit/gocron: [最終更新は3年前]
https://github.com/go-co-op/gocron: [上記パッケージのフォークで定期的にメンテナンスされています]
現在のメンテナーからの注意事項:このプロジェクトの現在メンテナンスされているフォークはhttps://github.com/go-co-op/gocronに移行されました
バックエンドWebサーバーのスケジューラを使用する方が、OSのcronjobよりも優れている理由:
環境に依存しない、つまりバックエンド言語がサポートされているすべてのオペレーティングシステムで動作する
様々な環境でのデプロイメントと運用が簡素化される
アプリケーションのコードベースと設定ファイルに統合される(バージョン管理される)
動的なスケーリング要件により適応的
アプリケーションの一部として実行されるため、バックエンドスケジューラはアプリケーションのコンテキスト、リソース、サービスに直接アクセスできる
より優れたエラー処理とログ記録
標準的なテスト手法を使用してアプリケーションと共にテストできる
アプリケーションのセキュリティコンテキスト内で動作し、権限管理を簡素化し、個別または特権的な権限に関連するセキュリティ問題のリスクを低減する
すべての*nix環境がenhanced cronをサポートしているわけではない
PaaSを使用している場合で、PaaSがスケジューリングやcronを提供していない場合でも、タスクをスケジュールできる
理解を深めましょう。
gocronを使用するために知っておく必要がある4つの概念があります。
タスク
ジョブ
スケジューラ
エグゼキューター
タスク:
ジョブによって実行される必要のあるGo関数です。
gocron.NewTask(
func(a string, b int) {
// do things
},
"hello",
1,
),
a and b are the parameter
we are passing "hello" and 1 to the function
ジョブ:
ジョブはタスクをカプセル化します
タスクをいつ実行すべきかの情報を含みます:
Duration: 固定のtime.Durationで実行
Random Duration: 最小値と最大値の間のランダムなtime.Durationで実行
Cron: crontabを使用して実行
Daily: 特定の時間に x 日ごとに実行
Weekly: 特定の曜日と時間に x 週ごとに実行
Monthly: 特定の日付と時間に x ヶ月ごとに実行
One Time: 特定の時間に一回だけ実行。これらは非繰り返しジョブです。
スケジューラ:
スケジューラはすべてのジョブを追跡し、実行準備ができたときに各ジョブをエグゼキューターに送信します。
エグゼキューター:
エグゼキューターはジョブのタスクを呼び出し、異なるジョブ実行タイミング要件の複雑さを管理します(例:互いに重複して実行されるべきではないシングルトン、実行中のジョブの最大数の制限など)
注:詳細については、ドキュメントをお読みください。
コーディングを始めましょう。
手順:
gocronパッケージをインストール
go get github.com/go-co-op/gocron/v2
スケジューラのインスタンスを作成
s, err := gocron.NewScheduler()
タスクを作成:
task := gocron.NewTask(
func(a string, b int) {
// do things
},
"hello",
1,
)
ジョブにタスクを割り当て:
j, err := s.NewJob(
gocron.DurationJob(
10*time.Second,
),
gocron.NewTask(task),
)
スケジュールを開始
s.Start()
以下のケースを実装してみましょう:
— タスクは毎日午前12時に実行する必要があり、タイムゾーンはAsia/Kathmandu。
package main
import (
"fmt"
"time"
"github.com/go-co-op/gocron/v2"
)
func main() {
// time location of Asia/Kathmandu
ktmLocation, err := time.LoadLocation("Asia/Kathmandu")
if err != nil {
// handle error
}
// create a scheduler
// assign time to our location
s, err := gocron.NewScheduler(
gocron.WithLocation(
ktmLocation,
),
)
if err != nil {
// handle error
}
task := gocron.NewTask(
func(a string, b int) {
// do things
// your business logic
},
"hello",
1,
)
// cron tab which run at 12am
// 2nd argument boolean is used for enhance cron
// check below for detail
jobType := gocron.CronJob(
"0 0 * * *",
false,
)
// add a job to the scheduler
j, err := s.NewJob(jobType, task)
if err != nil {
// handle error
}
// each job has a unique id
fmt.Println(j.ID())
// start the scheduler
s.Start()
// block until you are ready to shut down
select {
case <-time.After(time.Minute):
}
// when you're done, shut it down
err = s.Shutdown()
if err != nil {
// handle error
}
}
完了です。本当に簡単ですよね。
CRON:
従来のCron(分レベルの精度):分レベルの精度で動作し、毎秒を指定することはできません
Enhanced Cron(秒レベルの精度)[gocronもこれをサポート]:QuartzスケジューラやモダンなCronライクなタスクスケジューラ(例:プログラミングライブラリの一部の実装)のような一部のシステムは、秒レベルのスケジューリングを可能にします
ドキュメントを参照してください。使用方法は本当に簡単です。
README: https://github.com/go-co-op/gocron?tab=readme-ov-file#gocron-a-golang-job-scheduling-package
Go Docs: https://pkg.go.dev/github.com/go-co-op/gocron/v2#section-readme
gocronのその他の機能:
分散インスタンスをサポート
ジョブイベントはアクションをトリガーできる(リスナーをジョブに追加可能)
多くのジョブとスケジューラオプションが利用可能:
ジョブオプション:NewJobに引数を渡す
グローバルジョブオプション:NewSchedulerのWithGlobalJobOptionsオプションに引数を渡す
スケジューラオプション:NewSchedulerに引数を渡す
ログを有効化可能:Loggerインターフェースを実装するだけ
モニター:各ジョブの実行からメトリクスを収集可能。
テストをサポート
ありがとうございました!
この記事は、2024 年 6 月に弊社のエンジニア Mukesh Kumar Chaudhary が執筆し、日本語に翻訳したものです。
英語版はこちらをクリックしてください。
https://articles.wesionary.team/gocron-schedule-your-task-using-golang-4b110d6ec862
採用情報
私たちはプロダクト共創の仕組み化に取り組んでいます。プロダクト共創をリードするプロダクト・マネージャー、そして、私たちのビジョンを市場に届ける営業メンバーを募集しています!
開発パートナーをお探しの企業様へ
弊社は、グローバル開発のメリットを活かし、高い費用対効果と品質を両立しています。経験豊富で多様性のあるチームが、課題を正しく理解し、最適なシステムと優れた体験を実現します。業務システムの開発、新規事業の開発、業務効率化やDX化に関するお困りごと、ぜひ弊社にご相談ください。