信号中断时 Golang Clean 关闭
Golang Clean shutdown on Signal Interrupt
我正在尝试找到一种有效的方法来关闭我所有的 go 例程,一旦我得到我的 OS 中断信号。我在这里轮询事件(比如来自某个队列)并在 goroutine 中处理它。但是当我收到 OS 中断时,我想确保正在进行的作业在终止之前完成。我还需要在所有 goroutine 完成后才做一些额外的事情。下面的代码对我来说似乎工作正常,但是有什么 better/efficient 方法可以做到这一点吗?
package main
import (
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"time" // or "runtime"
)
func something(wg *sync.WaitGroup){
defer wg.Done()
fmt.Println("something is happening here...")
time.Sleep(10 * time.Second)
fmt.Println("job done...")
}
func main() {
c := make(chan os.Signal)
mutex := sync.Mutex{}
stop := make(chan int, 1)
signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
wg := sync.WaitGroup{}
count := 0
go func() {
<-c
currentTime := time.Now()
fmt.Println("Interrupt signal got at: ", currentTime.String())
// do not let the code shutdown without running everything we needed to do
mutex.Lock()
stop <- 1
fmt.Println("Done .. try shutting down")
wg.Wait()
// do cleanup
time.Sleep(3*time.Second)
fmt.Println("All cleanup completed .. shut down")
currentTime = time.Now()
fmt.Println("Kill at : ", currentTime.String())
mutex.Unlock()
}()
// This for loop is for reading messages from queue like sqs, and it has to be infinite loop because there might be scenarios where there are no events for period of time.
for {
// read off of queue
select {
case stop <- 1:
fmt.Println("Not stopped yet")
wg.Add(1)
go something(&wg)
<- stop
count ++
default:
// try getting the lock before exiting (so that other cleanups are done)
mutex.Lock()
fmt.Println("Done! All jobs completed: Jobs count",count)
return
}
fmt.Println("Processing job -", count)
time.Sleep(1 * time.Second)
}
}
我认为您的解决方案过于复杂。这可能是正确的,但这要简单得多:
func goroutine(wg *sync.WaitGroup,stop chan struct{}) {
defer wg.Done()
for {
select {
case <-stop:
return
default:
}
// do stuff
}
}
func main() {
stop:=make(chan struct{})
// Setup signal handlers
go func() {
<-c
// This will send the stop signal to all goroutines
close(stop)
}()
// Start goroutines
...
// wait for them to finish
wg.Wait()
我正在尝试找到一种有效的方法来关闭我所有的 go 例程,一旦我得到我的 OS 中断信号。我在这里轮询事件(比如来自某个队列)并在 goroutine 中处理它。但是当我收到 OS 中断时,我想确保正在进行的作业在终止之前完成。我还需要在所有 goroutine 完成后才做一些额外的事情。下面的代码对我来说似乎工作正常,但是有什么 better/efficient 方法可以做到这一点吗?
package main
import (
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"time" // or "runtime"
)
func something(wg *sync.WaitGroup){
defer wg.Done()
fmt.Println("something is happening here...")
time.Sleep(10 * time.Second)
fmt.Println("job done...")
}
func main() {
c := make(chan os.Signal)
mutex := sync.Mutex{}
stop := make(chan int, 1)
signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
wg := sync.WaitGroup{}
count := 0
go func() {
<-c
currentTime := time.Now()
fmt.Println("Interrupt signal got at: ", currentTime.String())
// do not let the code shutdown without running everything we needed to do
mutex.Lock()
stop <- 1
fmt.Println("Done .. try shutting down")
wg.Wait()
// do cleanup
time.Sleep(3*time.Second)
fmt.Println("All cleanup completed .. shut down")
currentTime = time.Now()
fmt.Println("Kill at : ", currentTime.String())
mutex.Unlock()
}()
// This for loop is for reading messages from queue like sqs, and it has to be infinite loop because there might be scenarios where there are no events for period of time.
for {
// read off of queue
select {
case stop <- 1:
fmt.Println("Not stopped yet")
wg.Add(1)
go something(&wg)
<- stop
count ++
default:
// try getting the lock before exiting (so that other cleanups are done)
mutex.Lock()
fmt.Println("Done! All jobs completed: Jobs count",count)
return
}
fmt.Println("Processing job -", count)
time.Sleep(1 * time.Second)
}
}
我认为您的解决方案过于复杂。这可能是正确的,但这要简单得多:
func goroutine(wg *sync.WaitGroup,stop chan struct{}) {
defer wg.Done()
for {
select {
case <-stop:
return
default:
}
// do stuff
}
}
func main() {
stop:=make(chan struct{})
// Setup signal handlers
go func() {
<-c
// This will send the stop signal to all goroutines
close(stop)
}()
// Start goroutines
...
// wait for them to finish
wg.Wait()