为什么 golang 的 CronJob 不能在 goroutine 中运行?

huangapple go评论90阅读模式
英文:

Why golang CronJob cannot run within goroutine?

问题

我每天使用CronJob来启动我的任务,我的任务有几个子任务,我计划使用goroutine来运行。然而,事情并不顺利。

文件框架

|-gpool
|  -pool.go
|-main.go

main.go

import (
	"code.byted.org/i18n_web/content_import_tool_cronJob/gpool"
	"fmt"
	"github.com/robfig/cron/v3"
	"log"
	"os"
	"runtime"
	"time"
)

func SeedJob(it string, pool *gpool.Pool){
	fmt.Println("Name item: ", it)
	println(runtime.NumGoroutine())
	pool.Done()
}

type delayJob struct {
	PagePatternNameList []string
}

func (j *delayJob) GetPagePatternNameList() {
	//j.PagePatternNameList = dal.GetPagePatternName()
	j.PagePatternNameList = []string{"atama_posts","cchan_posts", "cookdoor_posts", "cookpad_posts",
		"cookpad_recipe_seed", "kurashiru_posts", "lips_all_posts", "lips_product", "lips_product_sku_seed",
		"lips_rank", "press_posts", "voce_all_posts", "zozo_posts_women"}
}

func (j *delayJob)Run(){
	log.Println("delay Job RUN")
	//time.Sleep(2 * time.Second)
	// startSeedJob
	pool := gpool.New(10)
	println(runtime.NumGoroutine())
	for _, it := range j.PagePatternNameList {
		pool.Add(1)
		go SeedJob(it, pool)
	}
	pool.Wait()
	println(runtime.NumGoroutine())
}

func main() {
	c := cron.New(
		cron.WithLogger(
			cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))))

	_, err := c.AddJob("CRON_TZ=America/New_York @every 2m", cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&delayJob{}))
	if err != nil {
		fmt.Println("Cron Job err!")
		return
	}
	fmt.Println("it started")
	c.Start()

	defer c.Stop()

	time.Sleep(time.Second * 5)

}

pool.go

package gpool

import (
	"sync"
)

type Pool struct {
	queue chan int
	wg    *sync.WaitGroup
}

func New(size int) *Pool {
	if size <= 0 {
		size = 1
	}
	return &Pool{
		queue: make(chan int, size),
		wg:    &sync.WaitGroup{},
	}
}

func (p *Pool) Add(delta int) {
	for i := 0; i < delta; i++ {
		p.queue <- 1
	}
	for i := 0; i > delta; i-- {
		<-p.queue
	}
	p.wg.Add(delta)
}

func (p *Pool) Done() {
	<-p.queue
	p.wg.Done()
}

func (p *Pool) Wait() {
	p.wg.Wait()
}

当我运行我的代码时,它没有打印出我期望的任何信息,只有

it started
cron: 2021/06/10 13:41:21 start
cron: 2021/06/10 13:41:21 schedule, now=2021-06-10T13:41:21+08:00, entry=1, next=2021-06-10T13:43:21+08:00
Exiting.

Debugger finished with the exit code 0

看起来它没有触发错误,但没有正确运行。我该如何解决这个问题?

英文:

I use CronJob for starting my task everyday, and my task has several sub-tasks which I plan to use goroutine to run. However, things do not go smoothly.

File Framework

|-gpool
|  -pool.go
|-main.go

main.go

import (
&quot;code.byted.org/i18n_web/content_import_tool_cronJob/gpool&quot;
&quot;fmt&quot;
&quot;github.com/robfig/cron/v3&quot;
&quot;log&quot;
&quot;os&quot;
&quot;runtime&quot;
&quot;time&quot;
)
func SeedJob(it string, pool *gpool.Pool){
fmt.Println(&quot;Name item: &quot;, it)
println(runtime.NumGoroutine())
pool.Done()
}
type delayJob struct {
PagePatternNameList []string
}
func (j *delayJob) GetPagePatternNameList() {
//j.PagePatternNameList = dal.GetPagePatternName()
j.PagePatternNameList = []string{&quot;atama_posts&quot;,&quot;cchan_posts&quot;, &quot;cookdoor_posts&quot;, &quot;cookpad_posts&quot;,
&quot;cookpad_recipe_seed&quot;, &quot;kurashiru_posts&quot;, &quot;lips_all_posts&quot;, &quot;lips_product&quot;, &quot;lips_product_sku_seed&quot;,
&quot;lips_rank&quot;, &quot;press_posts&quot;, &quot;voce_all_posts&quot;, &quot;zozo_posts_women&quot;}
}
func (j *delayJob)Run(){
log.Println(&quot;delay Job RUN&quot;)
//time.Sleep(2 * time.Second)
// startSeedJob
pool := gpool.New(10)
println(runtime.NumGoroutine())
for _, it := range j.PagePatternNameList {
pool.Add(1)
go SeedJob(it, pool)
}
pool.Wait()
println(runtime.NumGoroutine())
}
func main() {
c := cron.New(
cron.WithLogger(
cron.VerbosePrintfLogger(log.New(os.Stdout, &quot;cron: &quot;, log.LstdFlags))))
_, err := c.AddJob(&quot;CRON_TZ=America/New_York @every 2m&quot;, cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&amp;delayJob{}))
if err != nil {
fmt.Println(&quot;Cron Job err!&quot;)
return
}
fmt.Println(&quot;it started&quot;)
c.Start()
defer c.Stop()
time.Sleep(time.Second * 5)
}

pool.go

package gpool
import (
&quot;sync&quot;
)
type Pool struct {
queue chan int
wg    *sync.WaitGroup
}
func New(size int) *Pool {
if size &lt;= 0 {
size = 1
}
return &amp;Pool{
queue: make(chan int, size),
wg:    &amp;sync.WaitGroup{},
}
}
func (p *Pool) Add(delta int) {
for i := 0; i &lt; delta; i++ {
p.queue &lt;- 1
}
for i := 0; i &gt; delta; i-- {
&lt;-p.queue
}
p.wg.Add(delta)
}
func (p *Pool) Done() {
&lt;-p.queue
p.wg.Done()
}
func (p *Pool) Wait() {
p.wg.Wait()
}

When I run my code, it did not print out any information I expected, just

it started
cron: 2021/06/10 13:41:21 start
cron: 2021/06/10 13:41:21 schedule, now=2021-06-10T13:41:21+08:00, entry=1, next=2021-06-10T13:43:21+08:00
Exiting.

Debugger finished with the exit code 0

It seems like it did not trigger an err, but not run correctly. How can I solve this?

答案1

得分: 2

它没有运行,因为你将作业安排为每2分钟运行一次,然后只等待了5秒钟,然后从main()返回,这导致你的程序退出。

如果你想在后台启动这个cron作业,你必须让程序运行足够长的时间,以便它能够运行和完成,至少在这个例子中要超过2分钟。

如果在main()中没有其他事情要做,你可以考虑使用c.Run()而不是c.Start()

英文:

It did not run because you scheduled the job to run every 2 minutes and then waited only 5 seconds, then you returned from main() which causes your program to exit.

If you want to start this cron in the background you must keep the program running long enough for it to run and complete, at least more than 2 minutes in this example.

If you have nothing else to do in main() then you might consider using c.Run() rather than c.Start().

huangapple
  • 本文由 发表于 2021年6月10日 13:56:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/67915507.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定