-
-
Save lemon-li/d8e94a27b83d6634aba0ac7bfc311b8f to your computer and use it in GitHub Desktop.
Graceful Shutdown Go App
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package graceful | |
import ( | |
"context" | |
"log" | |
"os" | |
"os/signal" | |
"sync" | |
"syscall" | |
"time" | |
) | |
// operation is a clean up function on shutting down | |
type Operation func(ctx context.Context) | |
// gracefulShutdown waits for termination syscalls and doing clean up operations after received it | |
func Shutdown(ctx context.Context, timeout time.Duration, ops []Operation) <-chan struct{} { | |
wait := make(chan struct{}) | |
go func() { | |
s := make(chan os.Signal, 1) | |
// add any other syscalls that you want to be notified with. | |
signal.Notify(s, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) | |
<-s | |
// set timeout for the ops to be done to prevent system hang. | |
// TODO: should to consider whether to timeout and exit directly. | |
timeoutFunc := time.AfterFunc(timeout, func() { | |
log.Printf("timeout %d ms has been elapsed, force exit", timeout.Milliseconds()) | |
os.Exit(1) | |
}) | |
defer timeoutFunc.Stop() | |
var wg sync.WaitGroup | |
// Do the operations asynchronously to save time. | |
for _, v := range ops { | |
wg.Add(1) | |
op := v | |
go func() { | |
defer wg.Done() | |
op(ctx) | |
}() | |
} | |
wg.Wait() | |
close(wait) | |
}() | |
return wait | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"fmt" | |
"log" | |
"net/http" | |
"time" | |
"git.shiyou.kingsoft.com/go/graceful" | |
) | |
func main() { | |
server := &http.Server{Addr: fmt.Sprintf(":%d", 9527)} | |
go func() { | |
server.ListenAndServe() | |
}() | |
wait := graceful.Shutdown( | |
context.Background(), | |
2 * time.Second, | |
[]graceful.Operation{ | |
func(ctx context.Context) { | |
server.Shutdown(ctx) | |
}, | |
} | |
) | |
<-wait | |
log.Println("Good bye ...") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment