在一个单独的gofiber进程中运行后台任务。

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

Run a background task in a SINGLE gofiber process

问题

我有一个后台任务(cleanUp),用于删除过时的文件。

func main() {
	// 最多4个进程/子进程
	runtime.GOMAXPROCS(4)

	// 启动清理定时任务
	go cleanUp()

    app := fiber.New(fiber.Config{
		Prefork:   true,
	})
	app.Post("/", handleFileupload)
	log.Fatal(app.Listen(":4000"))
}

func cleanUp() {
	fmt.Println("Cleaning Up..")
	for {
		// 在这里删除旧文件
		time.Sleep(60 * time.Second)
	}
}

目前,cleanUp 在所有4个进程上运行,并打印了4次Cleaning Up..

但是我希望它只在一个进程上运行,并打印一次Cleaning Up..。我尝试过使用waitGroups和通道,但未能实现我想要的效果。

如何使其只在一个进程上运行以避免竞争条件?

以下是输出:

Cleaning Up..

 ┌───────────────────────────────────────────────────┐  ┌───────────────────────────────────────────────────┐
 │                   Fiber v2.38.1                   │  │ Child PIDs ... 79378, 79379, 79380, 79381         │
 │               http://127.0.0.1:4000               │  └───────────────────────────────────────────────────┘
 │       (bound on host 0.0.0.0 and port 4000)       │ 
 │                                                   │ 
 │ Handlers ............. 5  Processes ........... 4 │ 
 │ Prefork ........ Enabled  PID ............. 79377 │ 
 └───────────────────────────────────────────────────┘ 

Cleaning Up..
Cleaning Up..
Cleaning Up..
Cleaning Up..
英文:

I have a background task (cleanUp) that deletes outdated files.

func main() {
	// 4 procs/childs max
	runtime.GOMAXPROCS(4)

	// start a cleanup cron-job
	go cleanUp()

    app := fiber.New(fiber.Config{
		Prefork:   true,
	})
	app.Post("/", handleFileupload)
	log.Fatal(app.Listen(":4000"))
}

func cleanUp() {
	fmt.Println("Cleaning Up..")
	for {
		// deletes old files here
		time.Sleep(60 * time.Second)
	}
}

At the moment cleanUp runs on all 4 processes and prints Cleaning Up.. 4 times.

But I want it to run only on a single process and print a single Cleaning Up... I have tried waitGroups and channels but failed to achieve what I wanted.

How can I run it only on a single process to avoid race conditions?

Here is the output:

Cleaning Up..

 ┌───────────────────────────────────────────────────┐  ┌───────────────────────────────────────────────────┐
 │                   Fiber v2.38.1                   │  │ Child PIDs ... 79378, 79379, 79380, 79381         │
 │               http://127.0.0.1:4000               │  └───────────────────────────────────────────────────┘
 │       (bound on host 0.0.0.0 and port 4000)       │ 
 │                                                   │ 
 │ Handlers ............. 5  Processes ........... 4 │ 
 │ Prefork ........ Enabled  PID ............. 79377 │ 
 └───────────────────────────────────────────────────┘ 

Cleaning Up..
Cleaning Up..
Cleaning Up..
Cleaning Up..

答案1

得分: 2

Fiber会生成多个进程来处理传入的请求。你需要在主进程中启动清理例程,并在子进程中跳过它。

Fiber提供了fiber.IsChild函数:

	// 启动清理定时任务
	if !fiber.IsChild() {
		go cleanUp()
	}

我稍微修改了你的示例,在处理程序和清理goroutine中打印进程ID:

func main() {
	// 最多4个进程/子进程
	runtime.GOMAXPROCS(4)

	// 启动清理定时任务
	if !fiber.IsChild() {
		go cleanUp()
	}

	app := fiber.New(fiber.Config{
		Prefork: true,
	})
	app.Post("/", handleFileupload)
	log.Fatal(app.Listen(":4000"))
}

func cleanUp() {
	fmt.Println("Cleaning Up.. Pid:", syscall.Getpid())
	for {
		// 在这里删除旧文件
		time.Sleep(1 * time.Second)
		fmt.Println("Cleaning Up.. Pid:", syscall.Getpid())
	}
}

func handleFileupload(ctx *fiber.Ctx) error {
	println("Upload: pid ", syscall.Getpid())
	return nil
}

结果:

Cleaning Up.. Pid: 27035

 ┌───────────────────────────────────────────────────┐  ┌───────────────────────────────────────────────────┐
 │                   Fiber v2.39.0                   │  │ Child PIDs ... 27041, 27042, 27044, 27045         │
 │               http://127.0.0.1:4000               │  └───────────────────────────────────────────────────┘
 │       (bound on host 0.0.0.0 and port 4000)       │ 
 │                                                   │ 
 │ Handlers ............. 1  Processes ........... 4 │ 
 │ Prefork ........ Enabled  PID ............. 27035 │ 
 └───────────────────────────────────────────────────┘ 

Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035

如你所见,清理只在主进程中运行。

英文:

Fiber spawns several processes to handle incoming requests. What you need is launch the cleanup routine in the master process and skip it in the child processes.

Fiber provides fiber.IsChild function:

	// start a cleanup cron-job
	if !fiber.IsChild() {
		go cleanUp()
	}

I slightly modified your example to print process ID in the handler and the cleanup goroutine:

func main() {
	// 4 procs/childs max
	runtime.GOMAXPROCS(4)

	// start a cleanup cron-job
	if !fiber.IsChild() {
		go cleanUp()
	}

	app := fiber.New(fiber.Config{
		Prefork: true,
	})
	app.Post("/", handleFileupload)
	log.Fatal(app.Listen(":4000"))
}

func cleanUp() {
	fmt.Println("Cleaning Up.. Pid:", syscall.Getpid())
	for {
		// deletes old files here
		time.Sleep(1 * time.Second)
		fmt.Println("Cleaning Up.. Pid:", syscall.Getpid())
	}
}

func handleFileupload(ctx *fiber.Ctx) error {
	println("Upload: pid ", syscall.Getpid())
	return nil
}

Result:

Cleaning Up.. Pid: 27035

 ┌───────────────────────────────────────────────────┐  ┌───────────────────────────────────────────────────┐
 │                   Fiber v2.39.0                   │  │ Child PIDs ... 27041, 27042, 27044, 27045         │
 │               http://127.0.0.1:4000               │  └───────────────────────────────────────────────────┘
 │       (bound on host 0.0.0.0 and port 4000)       │ 
 │                                                   │ 
 │ Handlers ............. 1  Processes ........... 4 │ 
 │ Prefork ........ Enabled  PID ............. 27035 │ 
 └───────────────────────────────────────────────────┘ 

Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035
Cleaning Up.. Pid: 27035

As you see, cleanup runs in the master process only.

huangapple
  • 本文由 发表于 2022年10月25日 03:34:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/74185954.html
匿名

发表评论

匿名网友

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

确定